home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
newsgrp
/
group90c.txt
< prev
next >
Wrap
Text File
|
1991-01-03
|
460KB
|
12,905 lines
From ralph Tue Oct 9 08:37:22 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA05206; Tue, 9 Oct 90 08:37:22 -0700
Date: Tue, 9 Oct 90 08:37:20 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9010091537.AA11439@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Tue, 9 Oct 90 08:37:20 MST
To: icon-group
Subject: large messages
Please remember that large e-mail messages cause some gateways, especially
PCs, to crash. If you're sending something over 20K or so characters,
please break it up into separate messages. If it's something like a
program, take care to identify the parts clearly.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From tenaglia@mis.mcw.edu Tue Oct 9 14:34:25 1990
Received: from rutgers.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03729; Tue, 9 Oct 90 14:34:25 -0700
Received: from uwm.UUCP by rutgers.edu (5.59/SMI4.0/RU1.4/3.08) with UUCP
id AA21071; Tue, 9 Oct 90 17:18:44 EDT
Received: by uwm.edu; id AA12064; Tue, 9 Oct 90 15:49:36 -0500
Received: from mcwmis by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Tue, 9 Oct 90 15:16:51 CDT
Received: by mis.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Tue, 9 Oct 90 15:15:31 CDT
Date: Tue, 9 Oct 90 15:15:31 CDT
Message-Id: <0093DF0203306BA0.2040083E@mis.mcw.edu>
From: "Chris Tenaglia - 257-8765" <tenaglia@mis.mcw.edu>
Subject: Time and Date Routines
To: icon-group@cs.arizona.edu
Perhaps I didn't look close enough at the IPL, but I am interested in time
and date manipulation routines. One the outside it sounds simple. Here're
the specs.
procedure dow(d) : Day of week. Should return either 1 through 7 or
Sunday through Saturday.
procedure difdate(d1,d2,uom) : Subtracts date d1 from date d2. uom is the
unit of measure for the result as seconds,
minutes, hours, days, weeks, months, years.
procedure future(d1,d2,uom) : Adds duration d2 to date d1, yielding answer.
duration in unit of measure uom, being either
seconds, minutes, hours, days, weeks, months,
years.
Date formats => YYYY-MMM-DD:HH:MM:SS
Month Day, Year HH:MM:SS
The routines should be smart enough to handle leap years, and be able to make
due with partial specs. 1990-oct-04 would default with 00:00:00. oct-04 would
also assume the current year. Examples...
difdate("oct-04","oct-16","day") returns 12
future("oct-02",6,"month") returns "1991-apr-02:00:00:00"
dow("oct-9") returns 3 or Tuesday
I think these might make a good addition to the IPL. Perhaps others have better
ideas. Is date manipulation of interest to anyone else? I haven't developed the
bodies of the procedures yet, but wonder if someone else has already?
Chris Tenaglia (System Manager)
Medical College of Wisconsin
8701 W. Watertown Plank Rd.
Milwaukee, WI 53226
(414)257-8765
tenaglia@mis.mcw.edu, mcwmis!tenaglia
From goer%sophist@gargoyle.uchicago.edu Tue Oct 9 21:41:04 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26047; Tue, 9 Oct 90 21:41:04 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Tue, 9 Oct 90 21:40 MST
Received: by gargoyle.uchicago.edu from sophist.uchicago.edu (5.59/1.14) id
AA15188; Tue, 9 Oct 90 23:40:27 199
Received: by sophist (4.1/UofC3.1X) id AA21196; Tue, 9 Oct 90 23:44:23 CDT
Resent-Date: Tue, 9 Oct 90 21:40 MST
Date: Tue, 9 Oct 90 23:44:23 CDT
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: parsing natural languages
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <20C82A039A47201ECF@Arizona.edu>
Message-Id: <9010100444.AA21196@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
I'm just curious what sort of work is being done in natural languages
using Icon. Naturally, I know of my own work in phonology and phonologi-
cal databases. I wonder, though, whether anyone out there has done very
much with the syntax of natural languages. A while back, I was working
on several different approaches to bottom-up parsing in Icon, but got a
bit sidetracked. I also tried implementing DFSA's in Icon, but found
it difficult to get them to run quickly, with reasonable memory require-
ments. Anyway, you can't parse natural languages with a DFSA. I'd ap-
preciate it very much if anyone who has worked in such areas - in Icon -
would drop me a line (or post a followup).
-Richard
From goer%sophist@gargoyle.uchicago.edu Tue Oct 9 22:27:56 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA27111; Tue, 9 Oct 90 22:27:56 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Tue, 9 Oct 90 22:27 MST
Received: by gargoyle.uchicago.edu from sophist.uchicago.edu (5.59/1.14) id
AA15801; Wed, 10 Oct 90 00:27:19 199
Received: by sophist (4.1/UofC3.1X) id AA21302; Wed, 10 Oct 90 00:31:14 CDT
Resent-Date: Tue, 9 Oct 90 22:27 MST
Date: Wed, 10 Oct 90 00:31:14 CDT
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: coaxing makes to handle Icon programs
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <20C19B5B464720263C@Arizona.edu>
Message-Id: <9010100531.AA21302@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
I often find that I can't coax make programs to handle Icon programs.
Since I send out a lot of code over this newsgroup, I have a vested
interest in making sure my makefiles work. Below is a shar archive
of a test program. If anyone is feeling adventurous, I'd appreciate
it very much if they would direct their adventursomeness in the fol-
lowing way: Un-shar the following archive, then make. Write me if
it doesn't work. Write me if it does work. Tell me your OS, and your
make program.
Note that the following shar archive can be "made" using gnu make.
I can't get it to work on my Xenix (SysVR3-based) system using the
stock make program. Nor can I get it to work using the stock Sun
make here on sophist. It "should" work, though. The fact that it
doesn't explains the ponderousness of the makefiles I distribute
with my programs.
-Richard
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
X.SUFFIXES: .u2 .icn .icn~
X
X.icn.u2:
X icont -c $*.icn
X.u2:
X icont -o $* $*.u1 $*.u2
X @/bin/rm $*.u?
X
Xall: tmp
SHAR_EOF
true || echo 'restore of Makefile failed'
rm -f _shar_wnt_.tmp
fi
# ============= s.tmp.icn ==============
if test -f 's.tmp.icn' -a X"$1" != X"-c"; then
echo 'x - skipping s.tmp.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting s.tmp.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 's.tmp.icn' &&
Xh11144
Xs 00003/00000/00000
Xd D 1.1 90/10/10 00:09:09 richard 1 0
Xc date and time created 90/10/10 00:09:09 by richard
Xe
Xu
XU
Xt
XT
XI 1
Xprocedure main()
Xwrite("hello")
Xend
XE 1
SHAR_EOF
true || echo 'restore of s.tmp.icn failed'
rm -f _shar_wnt_.tmp
fi
exit 0
From nickerso@SPUNKY.CS.NYU.EDU Wed Oct 10 16:41:20 1990
Received: from SPUNKY.CS.NYU.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA22368; Wed, 10 Oct 90 16:41:20 -0700
Received: by SPUNKY.CS.NYU.EDU (5.61/1.34)
id AA12133; Wed, 10 Oct 90 19:41:37 -0400
Date: Wed, 10 Oct 90 19:41:37 -0400
From: nickerso@SPUNKY.CS.NYU.EDU (Jeff Nickerson)
Message-Id: <9010102341.AA12133@SPUNKY.CS.NYU.EDU>
To: icon-group@cs.arizona.edu
Subject: desubscribe
Please desubscribe me from your electronic mailing list.
From icon-group-request@arizona.edu Fri Oct 12 07:11:29 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29291; Fri, 12 Oct 90 07:11:29 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 12 Oct 90 07:10 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA23854; Fri, 12 Oct 90
06:59:01 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 12 Oct 90 07:11 MST
Date: 10 Oct 90 20:57:37 GMT
From: eru!hagbard!sunic!mcsun!ukc!warwick!nott-cs!christopher-robin.cs.bham.ac.uk!lxg@bloom-beacon.mit.edu
Subject: An introduction to Icon?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <1EE6281A5AE7203E3F@Arizona.edu>
Message-Id: <1004@christopher-robin.cs.bham.ac.uk>
Organization: Birmingham University, England
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
I have just picked up version 8 of Icon and would like to
explore it further. Does anyone know if there is a tutorial
on it floating around and accessible by ftp?
Cheers
Griff, University of Birmingham.
-------------------------------------------------------------
-------------------------------------------------------------
From icon-group-request@arizona.edu Thu Oct 18 17:14:05 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA16109; Thu, 18 Oct 90 17:14:05 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 18 Oct 90 17:13 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA22642; Thu, 18 Oct 90
17:04:45 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 18 Oct 90 17:13 MST
Date: 17 Oct 90 23:35:34 GMT
From: bsu-cs!bsu-ucs!earlham!johnb@iuvax.cs.indiana.edu
Subject: Icon and Oracle. A great mix
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <19DAF65F7A0B206CB7@Arizona.edu>
Message-Id: <3145@yang.earlham.edu>
Organization: Earlham College, Richmond, Indiana
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
For anyone who is interested.....
At Earlham College (Heard of it?) we undertook a project of
intergrating Icon with the Oralce Relational Database. We are finished
now, and the project seems to have alot of potential.
Our interface is a new built in function called 'oracle' which
accepts any SQL statement (Not SQL*PLUS). The information is returned
through the list data type. All DMLs, DDL, and queries supported as well
as a new built in &OracleError code.
We chose Icon because it is such a strong language for use with
strings and text. Our intergration, called OraConIt allows for
sophisticated manipulation of the information returned. It could be used
as a SQL front end, or as a report writer, or for DBAs be able to
intergote the Data Dictionary and be able to process the data in a
high-level laguage. Samples of code written in PRO*C and OraCon are very
interesting to compare. (Of course OraCon takes less code.)
We have developed only a VAX/VMS version, but conversion to any
other platform should be painless. One needs the Oracle C run time
library and the source code for that version of Icon.
If you are interested by this little bit of info, (there is alot more)
drop me a 'line' here. I would love to get some feedback on it.
Thank you,
The OraCon Group
John Benjamin
Johnb@yang.Earlham.Edu
From kwalker Thu Oct 18 17:35:57 1990
Received: from gacham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA16751; Thu, 18 Oct 90 17:35:57 -0700
Date: Thu, 18 Oct 90 17:35:55 MST
From: "Kenneth Walker" <kwalker>
Message-Id: <9010190035.AA02399@gacham.cs.arizona.edu>
Received: by gacham.cs.arizona.edu; Thu, 18 Oct 90 17:35:55 MST
To: icon-group
Subject: Re: Icon and Oracle. A great mix
Date: 17 Oct 90 23:35:34 GMT
From: bsu-cs!bsu-ucs!earlham!johnb@iuvax.cs.indiana.edu
At Earlham College (Heard of it?) we undertook a project of
intergrating Icon with the Oralce Relational Database. We are finished
now, and the project seems to have alot of potential.
Our interface is a new built in function called 'oracle' which
accepts any SQL statement (Not SQL*PLUS). The information is returned
through the list data type.
Neat!
I was wondering if there is information that would be reasonable to
"generate" rather than return in a list (I don't know much about Oracle
or SQL, or data bases in general). Generating results is a more "Iconish"
approach to returning multiple homogenous results than using a data
structure. The programmer can then put them in a list if desired.
Ken Walker / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621-4252 kwalker@cs.arizona.edu {uunet|allegra|noao}!arizona!kwalker
From nowlin@iwtqg.att.com Fri Oct 19 05:17:25 1990
Resent-From: nowlin@iwtqg.att.com
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA11455; Fri, 19 Oct 90 05:17:25 -0700
Received: from att.att.com by Arizona.edu; Fri, 19 Oct 90 05:16 MST
Resent-Date: Fri, 19 Oct 90 05:17 MST
Date: Fri, 19 Oct 90 06:51 CDT
From: nowlin@iwtqg.att.com
Subject: RE: Icon and Oracle (SQL)
Resent-To: icon-group@cs.arizona.edu
To: att!arizona.edu!icon-group@cs.arizona.edu
Resent-Message-Id: <1975EF2F382B2077AF@Arizona.edu>
Message-Id: <1975F7C2F5958016D3@Arizona.edu>
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: att!arizona.edu!icon-group@cs.Arizona.edu
We've prototyped an interface to Informix that contains a single function
called sql(). This function is a generator that's passed an SQL
statement. It either fails or generates results.
If the SQL statement passed is a "select" statement the sql() procedure
generates a series of Icon tables that correspond to the records selected.
The keys to the tables are the field names selected and the values are the
corresponding values from the database.
If the SQL statement passed isn't a "select" statement the result generated
is the integer number of records in the database affected by the SQL
statement. For example, a "delete" statement with a where clause that
deleted 12 records from a database table would generate the single integer
12 before failing.
Right now this Informix interface is implemented as an Icon procedure that
calls a C program written with ESQL. We plan to eventually implement it as
a built-in function using a pi.
It would certainly be possible to use Oracle or most any database that
supports SQL the same way. There's a definite advantage to being able to
manipulate the results of a database query with Icon instead of C.
Jerry Nowlin
(...!att!iwtqg!nowlin)
From @mirsa.inria.fr:ol@cerisi.cerisi.Fr Fri Oct 19 13:47:52 1990
Resent-From: @mirsa.inria.fr:ol@cerisi.cerisi.Fr
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06197; Fri, 19 Oct 90 13:47:52 -0700
Received: from mirsa.inria.fr by Arizona.edu; Fri, 19 Oct 90 13:47 MST
Received: from cerisi.cerisi.fr by mirsa.inria.fr with SMTP (5.61+++/IDA-1.2.8)
id AA11424; Fri, 19 Oct 90 21:48:49 +0100
Resent-Date: Fri, 19 Oct 90 13:47 MST
Date: Fri, 19 Oct 90 21:45:28 -0100
From: Lecarme Olivier <ol@cerisi.cerisi.Fr>
Subject: Icon and X-windows
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <192E9AD0116B207EB8@Arizona.edu>
Message-Id: <9010192048.AA11424@mirsa.inria.fr>
Posted-Date: Fri, 19 Oct 90 21:45:28 -0100
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
I have the project of using the variant translator capability of Icon,
as well as the personalized interpreter, in order to define an extension
to Icon interfaced with X-windows. The idea would be to have a very
powerful and flexible language for prototyping interactive graphic
environments.
Has anybody already attempted something similar? Has anybody any
interesting idea about this matter?
Olivier Lecarme
From cjeffery Fri Oct 19 14:51:13 1990
Resent-From: "Clinton Jeffery" <cjeffery>
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA09356; Fri, 19 Oct 90 14:51:13 -0700
Received: from megaron.cs.Arizona.EDU by Arizona.edu; Fri, 19 Oct 90 14:50 MST
Received: from caslon.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via
SMTP id AA09319; Fri, 19 Oct 90 14:50:33 -0700
Received: by caslon.cs.arizona.edu; Fri, 19 Oct 90 14:50:30 -0700
Resent-Date: Fri, 19 Oct 90 14:50 MST
Date: Fri, 19 Oct 90 14:50:30 -0700
From: Clinton Jeffery <cjeffery@cs.arizona.edu>
Subject: Icon and X-windows
Resent-To: icon-group@cs.arizona.edu
To: ol@cerisi.cerisi.Fr
Cc: icon-group@arizona.edu
Resent-Message-Id: <1925C158F62B2075CA@Arizona.edu>
Message-Id: <9010192150.AA06946@caslon.cs.arizona.edu>
In-Reply-To: Lecarme Olivier's message of Fri, 19 Oct 90 21:45:28 -0100
<9010192048.AA11424@mirsa.inria.fr>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: ol@cerisi.cerisi.Fr
X-Vms-Cc: icon-group@Arizona.EDU
We are using an Icon X Windows interface internally here in our
program visualization research. There is a 15 page reference
document describing it, Icon Project Document 150. The interface
is built on top of Xlib. There is no public distribution that
includes the X Windows interface at this time.
Interested persons may obtain more information from me by electronic
mail. I would also enjoy hearing from persons who are working on
Icon interfaces to other window systems.
Clint Jeffery, U. of Arizona Dept. of Computer Science
cjeffery@cs.arizona.edu -or- {noao allegra}!arizona!cjeffery
From goer@midway.uchicago.edu Sat Oct 20 23:52:57 1990
Resent-From: goer@midway.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03592; Sat, 20 Oct 90 23:52:57 -0700
Received: from midway.uchicago.edu by Arizona.edu; Sat, 20 Oct 90 23:52 MST
Received: from quads.uchicago.edu (quads.uchicago.edu) by midway.uchicago.edu
Sun, 21 Oct 90 01:52:24 CDT
Resent-Date: Sat, 20 Oct 90 23:52 MST
Date: Sun, 21 Oct 90 01:52:24 CDT
From: "Richard L. Goerwitz" <goer@midway.uchicago.edu>
Subject: test posting of dir lister
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <1810E919AC6B20793F@Arizona.edu>
Message-Id: <9010210652.AA08963@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
It's hard to get directory listings from within Icon. Here are
some routines that do this in a generic way. The idea of doing
things generically is to avoid OS-specificity, at least on the
level on which these routines are called (not, in other words,
in the actual mechanics of how to get the listing, which are very
OS-specific).
Anyway, I hope someone finds these routines useful.
-Richard
############################################################################
#
# Name: gdl.icn
#
# Title: Get directory list
#
# Author: Richard L. Goerwitz
#
# Version: 1.2
#
############################################################################
#
# Gdl returns a list containing everything in a directory (whose name
# must be passed as an argument to gdl). Nothing fancy. I use this file
# as a template, modifying the procedures according to the needs of the
# program in which they are used.
#
############################################################################
#
# Requires: UNIX or MS-DOS
#
############################################################################
procedure gdl(dir)
getdir := set_getdir_by_os()
return getdir(dir)
end
procedure set_getdir_by_os()
# Decide how to get a directory, based on whether we are running
# under Unix or MS-DOS.
if find("UNIX", &features)
then return unix_get_dir
else if find("MS-DOS", &features)
then return msdos_get_dir
else stop("Your operating system is not (yet) supported.")
end
procedure msdos_get_dir(dir)
# Returns a sorted list of all filenames (full paths included) in
# directory "dir." The list is sorted. Fails on invalid or empty
# directory. Aborts if temp file cannot be opened.
#
# Temp files can be directed to one or another directory either by
# manually setting the variable temp_dir below, or by setting the
# value of the environment variable TEMPDIR to an appropriate
# directory name.
local in_dir, filename_list, line
static temp_dir
initial {
temp_dir :=
(trim(map(getenv("TEMPDIR"), "/", "\\"), '\\') || "\\") |
".\\"
}
# Get name of tempfile to be used.
temp_name := get_dos_tempname(temp_dir) |
stop("No more available tempfile names!")
# Make sure we have an unambiguous directory name, with backslashes
# instead of Unix-like forward slashes.
dir := trim(map(dir, "/", "\\"), '\\') || "\\"
# Put dir listing into a temp file.
system("dir "||dir||" > "||temp_name)
# Put tempfile entries into a list, removing blank- and
# space-initial lines. Exclude directories (i.e. return file
# names only).
in_dir := open(temp_name,"r") |
stop("Can't open temp file in directory ",temp_dir,".")
filename_list := list()
every filename := ("" ~== !in_dir) do {
match(" ",filename) | find(" <DIR>", filename) & next
# Exclude our own tempfiles (may not always be appropriate).
filename ?:= trim(trim(tab(10)) || "." || tab(13), '. ')
put(filename_list, map(dir || filename))
}
# Clean up.
close(in_dir) & remove(temp_name)
# Check to be sure we actually managed to read some files.
if *filename_list = 0 then fail
else return sort(filename_list)
end
procedure get_dos_tempname(dir)
# Don't clobber existing files. Get a unique temp file name for
# use as a temporary storage site.
every temp_name := dir || "icondir." || right(string(1 to 999),3,"0") do {
temp_file := open(temp_name,"r") | break
close(temp_file)
}
return \temp_name
end
procedure unix_get_dir(dir)
dir := trim(dir, '/') || "/"
filename_list := list()
in_dir := open("/bin/ls -F "||dir, "pr")
every filename := ("" ~== !in_dir) do {
match("/",filename,*filename) & next
put(filename_list, trim(dir || filename, '*'))
}
close(in_dir)
if *filename_list = 0 then fail
else return filename_list
end
From ralph Tue Oct 23 05:38:12 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26192; Tue, 23 Oct 90 05:38:12 -0700
Date: Tue, 23 Oct 90 05:38:08 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9010231238.AA23237@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Tue, 23 Oct 90 05:38:08 MST
To: icon-group
Subject: Message forwarded by request
For anyone who is interested.....
At Earlham College (Heard of it?) we undertook a project of
intergrating Icon with the Oralce Relational Database. We are finished
now, and the project seems to have alot of potential.
Our interface is a new built in function called 'oracle' which
accepts any SQL statement (Not SQL*PLUS). The information is returned
through the list data type. All DMLs, DDL, and queries supported as well
as a new built in &OracleError code.
We chose Icon because it is such a strong language for use with
strings and text. Our intergration, called OraConIt allows for
sophisticated manipulation of the information returned. It could be used
as a SQL front end, or as a report writer, or for DBAs be able to
intergote the Data Dictionary and be able to process the data in a
high-level laguage. Samples of code written in PRO*C and OraCon are very
interesting to compare. (Of course OraCon takes less code.)
We have developed only a VAX/VMS version, but conversion to any
other platform should be painless. One needs the Oracle C run time
library and the source code for that version of Icon.
If you are interested by this little bit of info, (there is alot more)
drop me a 'line' here. I would love to get some feedback on it.
Thank you,
The OraCon Group
John Benjamin
Johnb@yang.Earlham.Edu
From goer%sophist@gargoyle.uchicago.edu Tue Oct 23 18:56:58 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03478; Tue, 23 Oct 90 18:56:58 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Tue, 23 Oct 90 18:56 MST
Received: by gargoyle.uchicago.edu from sophist.uchicago.edu (5.59/1.14) id
AA16775; Tue, 23 Oct 90 20:56:22 199
Received: by sophist (4.1/UofC3.1X) id AA07035; Tue, 23 Oct 90 21:00:05 CDT
Resent-Date: Tue, 23 Oct 90 18:56 MST
Date: Tue, 23 Oct 90 21:00:05 CDT
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: BCD
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <15DEC3453B0B209EA7@Arizona.edu>
Message-Id: <9010240200.AA07035@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
I recall someone posting some nice little routines that turned
integers into binary coded decimal strings. I remember looking
at them and thinking they looked useful.
I wonder if these are still around somewhere.
-Richard (goer@sophist.uchicago.edu)
From tenaglia@mis.mcw.edu Wed Oct 24 11:35:43 1990
Received: from rutgers.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA08895; Wed, 24 Oct 90 11:35:43 -0700
Received: from uwm.UUCP by rutgers.edu (5.59/SMI4.0/RU1.4/3.08) with UUCP
id AA24606; Wed, 24 Oct 90 14:21:50 EDT
Received: by uwm.edu; id AA22598; Wed, 24 Oct 90 13:02:18 -0500
Received: from mcwmis by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Wed, 24 Oct 90 11:59:16 CDT
Received: by mis.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Wed, 24 Oct 90 08:15:25 CDT
Date: Wed, 24 Oct 90 08:15:25 CDT
Message-Id: <0093EA90CFB67D60.20400660@mis.mcw.edu>
From: "Chris Tenaglia - 257-8765" <tenaglia@mis.mcw.edu>
Subject: Packed Decimal Procedures
To: icon-group@cs.arizona.edu
Here are the procedures pack() and unpack(). They are part of my
personal IPL. Most of my icon programs have so much in common that
this 10 module library I use as a program starter. I 'include' the
file into the editor, chop out from 2 to 7 modules, and begin coding
while line := read(in) do
{
HERE
}
which is pretty good in regards to 'reusable modules' or 'software chips',
the chief goal of ADA and OOPS. I wonder if anyone else has developed
their own 'software chips' or 'program starter'?
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
##################################################################
# #
# THIS PROCEDURE PACKS AN INTEGER IN TO PACKED DECIMAL STRING. #
# #
##################################################################
procedure pack(num,width)
local int,sign,prep,packed,i,word
(int := integer(num)) | fail
if int < 0 then sign := "=" else sign := "<"
prep := int || sign
packed := ""
if (*prep % 2) ~= 0 then prep := "0" || prep
every i := 1 to *prep by 2 do
{
word := prep[i+:2]
if word[-1] == ("=" | "<") then
{
packed ||:= char(word[1]*16 + ord(word[2])-48)
next
}
packed ||:= char(word[1]*16 + word[2])
}
/width := *packed
return right(packed,width,"\0")
end
##################################################################
# #
# THIS PROCEDURE UNPACKS A VALUE INTO AN INTEGER. USING THIS #
# CODE SEGMENT REQUIRES LINKING WITH RADCON FROM THE IPL. #
# #
##################################################################
procedure unpack(val,width)
local tmp,number,tens,ones,sign
tmp := ""
sign := 1
every number := ord(!val) do
tmp ||:= right(map(radcon(number,10,16),&lcase,&ucase),2,"0")
if tmp[-1] == ("B" | "D") then sign := -1
tmp[-1] := ""
tmp *:= sign
/width := *tmp
return right(tmp,width)
end
From sboisen@BBN.COM Wed Oct 24 13:06:05 1990
Message-Id: <9010242006.AA03609@megaron.cs.arizona.edu>
Received: from SLANG.BBN.COM by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03609; Wed, 24 Oct 90 13:06:05 -0700
To: tenaglia@mis.mcw.edu
Cc: icon-group@cs.arizona.edu
In-Reply-To: Chris Tenaglia - 257-8765's message of Wed, 24 Oct 90 08:15:25 CDT <0093EA90CFB67D60.20400660@mis.mcw.edu>
Subject: Packed Decimal Procedures
From: Sean Boisen <sboisen@BBN.COM>
Sender: sboisen@BBN.COM
Reply-To: sboisen@BBN.COM
Date: Wed, 24 Oct 90 16:02:47 EDT
> I wonder if anyone else has developed
> their own 'software chips' or 'program starter'?
>
> Chris Tenaglia (System Manager) | Medical College of Wisconsin
> 8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
> (414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
Since most of the Icon code i write is for small Unix-like utilities,
i frequently care about setting up handling for command line
arguments. My basic template therefore looks like this (i believe i
got this from one of the newsletters):
----------------------------------------------------------------------
#
procedure main(cmdline)
local switch
while switch := get(cmdline) do
{
case switch of
{
"-t": tswitch := 1
"-l": limit := integer(get(cmdline)) | Usage()
default: Usage()
}
}
end
# stop, informing of incorrect usage
#
procedure Usage()
stop("usage for : [-t] [-l n]")
end
----------------------------------------------------------------------
This gives me two examples of command line switches, one with and one
without args, and an helpful message if i get the args wrong.
Typically the first thing i do is edit the args and usage message, and
then start working on the guts of the thing.
........................................
Sean Boisen -- sboisen@bbn.com
BBN Systems and Technologies, Cambridge MA
From icon-group-request@arizona.edu Thu Oct 25 11:49:31 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA17695; Thu, 25 Oct 90 11:49:31 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 25 Oct 90 11:48 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA09800; Thu, 25 Oct 90
11:37:45 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 25 Oct 90 11:48 MST
Date: 25 Oct 90 01:32:31 GMT
From: att!linac!midway!quads.uchicago.edu!goer@ucbvax.Berkeley.EDU
Subject: RE: Packed Decimal Procedures
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <14882FAEA41520A50F@Arizona.edu>
Message-Id: <1990Oct25.013231.21009@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
References: <0093EA90CFB67D60.20400660@mis.mcw.edu>
Tenaglia@mis.mcw.edu ("Chris Tenaglia - 257-8765") writes:
>
>Here are the procedures pack() and unpack(). They are part of my
>personal IPL.
I couldn't resist toying with the (un)pack routines just posted.
There's no reason I can see for storing the sign if the int is
positive, so I cut that part out. I also added another unpack
routine, which runs a bit faster, and behaves somewhat differently
than the one Chris wrote.
Oh, I should perhaps add that the thing has been redone in IPL
format, and I've eliminated most automatic type conversions.
They automatic type conversion thing is just a pet peeve of mine.
I hope no one holds it against me :-).
-Richard
############################################################################
#
# Name: packunpk.icn
#
# Title: Pack and unpack packed-decimal strings
#
# Author: Chris Tenaglia (modified by Richard L. Goerwitz)
#
# Version: 1.1
#
############################################################################
#
# Integers written directly as strings occupy much more space
# than they need to. One easy way to shrink them a bit is to "pack"
# them, i.e. convert each decimal digit into a four-byte binary
# code, and pack these four-bit chunks into eight-bit characters,
# which can be written to a file.
#
# Interestingly, packing decimal strings in this manner lends
# itself to unpacking by treating each character as a base-10
# integer, and then converting it to base-16. Say we have an input
# string "99." Pack() would convert it to an internal representation
# of char(16*9 + 9), i.e. char(153). Unpack would treat this
# char(153) representation as a base-10 integer, and convert it to
# base 16 (i.e. 10r153 -> 16r99). The 99 is, of course, what we
# started with.
#
# Note that two unpack routines are provided here: The first, by
# Tanaglia, utilizes radcon.icn from the IPL. The second, by
# Goerwitz, does not. They utilize very different methods, but both
# amount to basically the same thing. Goerwitz's routine returns an
# integer, though, and has no "width" argument.
#
############################################################################
#
# Links: radcon.icn
#
############################################################################
# link radcon.icn
procedure pack(num,width)
# THIS PROCEDURE PACKS AN INTEGER INTO A PACKED DECIMAL STRING.
local int, sign, prep, packed, word
int := integer(num) | fail
# There's really no need to store the sign if it's positive.
if int < 0 then sign := "=" else sign := ""
prep := string(abs(int)) || sign
packed := ""
if (*prep % 2) ~= 0 then prep := "0" || prep
prep ? {
while word := move(2) do {
if pos(0)
then packed ||:= char(integer(word[1])*16 + ord(word[2])-48)
else packed ||:= char(integer(word[1])*16 + integer(word[2]))
}
}
/width := *packed
return right(packed, width, "\0")
end
procedure unpack(val,width)
# THIS PROCEDURE UNPACKS A VALUE INTO A STRING-INTEGER. USING THIS
# CODE SEGMENT REQUIRES LINKING WITH RADCON FROM THE IPL.
local tmp, number, tens, ones, sign
tmp := ""
sign := 1
every number := ord(!val) do
tmp ||:= right(map(radcon(number,10,16),&lcase,&ucase),2,"0")
if tmp[-1] == ("B" | "D") then {
sign := -1
tmp[-1] := ""
}
tmp *:= sign
/width := *string(tmp)
return right(string(tmp), width)
end
procedure unpack2(val)
# THIS PROCEDURE UNPACKS A VALUE INTO AN STRING-INTEGER.
local unpacked, int
unpacked := ""
val ? {
while int := ord(move(1)) do {
unpacked ||:= string(iand(2r11110000,int) / 16)
if pos(0) then {
if iand(2r00001111,int) = 13 then {
unpacked := "-" || unpacked
break
}
}
unpacked ||:= string(iand(2r00001111,int))
}
}
return integer(unpacked)
end
From tenaglia@mis.mcw.edu Sat Oct 27 08:23:20 1990
Received: from rutgers.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA09782; Sat, 27 Oct 90 08:23:20 -0700
Received: from uwm.UUCP by rutgers.edu (5.59/SMI4.0/RU1.4/3.08) with UUCP
id AA07803; Sat, 27 Oct 90 11:16:11 EDT
Received: by uwm.edu; id AA12078; Sat, 27 Oct 90 09:51:02 -0500
Received: from mcwmis by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Sat, 27 Oct 90 08:59:29 CDT
Received: by mis.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Sat, 27 Oct 90 08:29:55 CDT
Date: Sat, 27 Oct 90 08:29:55 CDT
Message-Id: <0093ECEE55262040.20400CCB@mis.mcw.edu>
From: "Chris Tenaglia - 257-8765" <tenaglia@mis.mcw.edu>
Subject: pack and unpack routines
To: icon-group@cs.arizona.edu
regarding : suggested enhancements to the pack & unpack routines
>
>Tenaglia@mis.mcw.edu ("Chris Tenaglia - 257-8765") writes:
>>
>>Here are the procedures pack() and unpack(). They are part of my
>>personal IPL.
>
>I couldn't resist toying with the (un)pack routines just posted.
>There's no reason I can see for storing the sign if the int is
>positive, so I cut that part out. I also added another unpack
>routine, which runs a bit faster, and behaves somewhat differently
>than the one Chris wrote.
>
>Oh, I should perhaps add that the thing has been redone in IPL
>format, and I've eliminated most automatic type conversions.
>They automatic type conversion thing is just a pet peeve of mine.
>I hope no one holds it against me :-).
>
>-Richard
MORE,...
The reason I handled the sign in the manner I did was that DEC and IBM
computers actually handle numbers in that format in some modes of operation.
Other language programs (COBOL, BASIC, FORTRAN, etc,..) may still need
access to those numbers for some reason, thus I maintained the sign, even
though it cost me 4 bits. Your versions are fine so long as icon programs
using this are the only accessors to the data.
Chris Tenaglia (System Manager)
Medical College of Wisconsin
8701 W. Watertown Plank Rd.
Milwaukee, WI 53226
(414)257-8765
tenaglia@mis.mcw.edu, mcwmis!tenaglia
From cary@hpcllak.cup.hp.com Wed Oct 31 16:10:31 1990
Received: from relay.hp.com (hp-sde.sde.hp.com) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA13689; Wed, 31 Oct 90 16:10:31 -0700
Received: from hpcllak.cup.hp.com by relay.hp.com with SMTP
(16.5/15.5+IOS 3.13) id AA29399; Wed, 31 Oct 90 15:10:27 -0800
Message-Id: <9010312310.AA29399@relay.hp.com>
Received: by hpcllak; Wed, 31 Oct 90 15:09:41 pst
Date: Wed, 31 Oct 90 15:09:41 pst
From: Cary Coutant <cary@hpcllak.cup.hp.com>
To: icon-group@cs.arizona.edu
Subject: date arithmetic
> Perhaps I didn't look close enough at the IPL, but I am interested in time
> and date manipulation routines.
Well, it doesn't quite meet your specs, but I have here a set of Icon
procedures that convert dates to and from Julian day numbers. Given the
Julian day numbers, you can do all of the arithmetic you like and the
convert back.
These routines are as correct as I can establish from a several sources,
the most helpful ones being the _Astronomical_Calendar_ (annual) and
_Astronomical_Companion_, both by Guy Ottewell (great books, both!).
I got the trick for converting month number to days-in-year-so-far from
some well-known published calculator algorithms floating around the net.
-Cary Coutant, Hewlett-Packard Computer Language Laboratory
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Cary Coutant <cary@hpcllak> on Wed Oct 31 15:04:41 1990
#
# This archive contains:
# jdate.icn
#
LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH
echo x - jdate.icn
cat >jdate.icn <<'@EOF'
# Note: "Julian day" is named after the father of the astronomer who
# invented the Julian day numbering system. It is unrelated to the
# "Julian calendar", which was the one established by Julius Caesar,
# and introduced the concept of a leap year every fourth year. The
# Gregorian calendar, established by Pope Gregory the somethingorother,
# corrected the Julian calendar by eliminating three leap years out of
# every four hundred years, bringing the average year to a length of
# 365 + 1/4 - 3/100 = 365.22 days.
# By the way, to astronomers (and to this program), the year 1 B.C.
# is year 0, 2 B.C. is -1, etc.
global cutover # julian day number of cutover from Julian to
# Gregorian calendar (should be the first day
# skipped).
procedure main(args)
cutover := julian(9, 3, 1752) # England and the Colonies
if !args == "-c" then cutover := julian(10, 5, 1582) # Catholic countries
convert()
return
end
procedure convert()
local g
while read() ? {
month := integer(tab(many('0123456789')))
tab(many(' /'))
day := integer(tab(many('0123456789')))
tab(many(' /'))
year := integer(tab(many('-0123456789')))
g := gregorian(month, day, year)
write(datestring(g), " = ", g)
}
return
end
## gregorian(m,d,y) - Return the Julian day number for 12:00 noon
# on the given m/d/y, using the Gregorian calendar.
procedure gregorian(month, day, year)
local g
g := julian(month, day, year)
if g >= cutover then {
if month < 3 then year -:= 1
g +:= 2 - floor(year/100.0) + floor(year/400.0)
}
return g
end
## julian(m,d,y) - Return the Julian day number for 12:00 noon
# on the given m/d/y, using the Julian calendar.
procedure julian(month, day, year)
month -:= 3
if month < 0 then {
month +:= 12
year -:= 1
}
return 1721117 + floor(year*365.25) + (month*153+2)/5 + day
end
## datestring() - produces a formatted date string for a julian day number.
procedure datestring(g)
local dow, mdy, m, d, y
dow := dayofweek(g)
mdy := tomdy(g)
m := mdy[1]
d := mdy[2]
y := mdy[3]
return left(dow, 10) ||
right(m, 2, "0") || "/" ||
right(d, 2, "0") || "/" ||
(right(0<y, 4, "0") | (right(1-y, 4, "0") || "BC"))
end
## dayofweek() - returns day of the week for a julian day number.
procedure dayofweek(g)
local dow
dow := g % 7
if dow < 0 then dow +:= 7
return (dow+1)("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday")
end
## tomdy() - converts julian day number to a list [m,d,y].
procedure tomdy(g)
local month, day, year, qc, c
day := g - 1721117 - 1 # 3/1/0000 = 0
# eliminate gregorian calendar correction
if g >= cutover then {
qc := floor(day/146097.0)
c := floor((day-qc*146097)/36525.0)
day +:= c + qc*3 - 2
}
year := floor((day*4+3)/1461.0)
day -:= floor(year*1461/4.0)
month := (day*5+2)/153
day := day - (month*153+2)/5 + 1
month +:= 3
if month > 12 then {
month -:= 12
year +:= 1
}
return [month, day, year]
end
## floor() - rounds to an integer towards negative infinity.
procedure floor(f)
local i
i := integer(f)
if i > f then i -:= 1
return i
end
## test() - Tests the date conversion routines by brute force,
# by stepping through day by day through the years 1601 to 2000.
#
# procedure test()
# local g, year, month, day, mdy
#
# g := julian(1, 1, 1601)
# every year := 1601 to 2000 do {
# every month := 1 to 12 do {
# every day := 1 to ndays(year, month) do {
# if year = 1752 & month = 9 & 2 < day < 14 then next
# g1 := gregorian(month, day, year)
# if g ~= g1 then
# write("gregorian(", month, "/", day, "/", year, ") is ",
# g1, ", should be ", g)
# mdy := tomdy(g)
# if mdy[1] ~= month | mdy[2] ~= day | mdy[3] ~= year then
# write("tomdy(", g, ") is ",
# mdy[1], "/", mdy[2], "/", mdy[3],
# ", should be ",
# month, "/", day, "/", year)
# g +:= 1
# }
# }
# if year % 25 = 0 then write(year)
# }
# return
# end
#
# procedure ndays(year, month)
# local mdays
# static stdyear, leapyear
#
# initial {
# stdyear := [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
# leapyear := [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
# }
#
# mdays := stdyear
# if year % 4 = 0 then mdays := leapyear
# if (1752 < year) % 400 = (100|200|300) then mdays := stdyear
# return .mdays[month]
# end
@EOF
chmod 664 jdate.icn
exit 0
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Fri Nov 2 14:13:59 1990
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA27706; Fri, 2 Nov 90 14:13:59 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA04865; Fri, 2 Nov 90 16:13:55 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Fri, 2 Nov 90 16:09:19 EST
Date: Fri, 2 Nov 90 14:33:12 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <266508@Wayne-MTS>
Subject: Generating variables
The Icon operator ! generates a sequence of variables when it's applied to
a list, string, or record. My question is: is there any way that a
user-defined procedure can generate variables (other than using the "variable"
function)? Here is my attempt at it; it didn't work.
Paul Abrahams
abrahams%wayne-mts@um.cc.umich.edu
procedure main ()
l := [1,2,3,4]
every writes(!l, " ")
write() # writes 1 2 3 4
every !l := 9
every writes(!l, " ")
write() # writes 9 9 9 9
every !p1(l) := 7 # produces an error; can't assign 7 to "9"
every writes(!l, " ")
write()
end
procedure p1(z)
suspend !z
end
From cary@hpcllak.cup.hp.com Fri Nov 2 16:04:49 1990
Received: from relay.hp.com ([15.255.152.2]) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA01495; Fri, 2 Nov 90 16:04:49 -0700
Received: from hpcllak.cup.hp.com by relay.hp.com with SMTP
(16.5/15.5+IOS 3.13) id AA26865; Fri, 2 Nov 90 15:03:48 -0800
Message-Id: <9011022303.AA26865@relay.hp.com>
Received: by hpcllak; Fri, 2 Nov 90 15:03:02 pst
Date: Fri, 2 Nov 90 15:03:02 pst
From: Cary Coutant <cary@hpcllak.cup.hp.com>
To: icon-group@cs.arizona.edu
Subject: Generating variables
The program would have worked but for a double bang -- you applied
the bang operator within the procedure, and on the procedure call.
Removing the latter yields a program that does what you were
expecting.
-Cary Coutant, HP Computer Language Lab
procedure main ()
l := [1,2,3,4]
every writes(!l, " ")
write() # writes 1 2 3 4
every !l := 9
every writes(!l, " ")
write() # writes 9 9 9 9
every p1(l) := 7 # no extra bang operator here
every writes(!l, " ")
write()
end
procedure p1(z)
suspend !z
end
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Sat Nov 3 02:13:57 1990
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14051; Sat, 3 Nov 90 02:13:57 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA01640; Sat, 3 Nov 90 04:13:51 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Sat, 3 Nov 90 04:10:13 EST
Date: Fri, 2 Nov 90 22:52:16 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <266657@Wayne-MTS>
Subject: Dereferencing
Yes, Beth was absolutely right about the way to fix my example of a generator
that returns variables.
I find it interesting that Icon attempts to preserve the "variable"-ness of
a returned entity, dereferencing it only if it has to. But I can't think of a
way of moving a variable in the other direction: from caller to callee. Not
only does Icon have call-by-value---there doesn't seem to be any way to
circumvent it. Or is there------?
Paul
Paul Abrahams
abrahams%wayne-mts@um.cc.umich.edu
From icon-group-request@arizona.edu Fri Nov 9 02:27:38 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14768; Fri, 9 Nov 90 02:27:38 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 9 Nov 90 02:27 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19952; Fri, 9 Nov 90 01:17:06
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 9 Nov 90 02:27 MST
Date: 8 Nov 90 19:35:41 GMT
From: wuarchive!cs.utexas.edu!news-server.csri.toronto.edu!clyde.concordia.ca!NSTN.NS.CA!cs.dal.ca!dal1!06davis@decwrl.dec.com
Subject: What are ICONS?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <090D2BD08B19A041D2@Arizona.edu>
Message-Id: <2219@ac.dal.ca>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
Please forgive me, all those who are knowledgeable, but what are icons
as applied to computers. I know that they are in plain 'ol English, but what
are they and what kind of system do they run on?
No flames please, I might just go and slit my wrists.
Davis B.
From icon-group-request@arizona.edu Fri Nov 9 09:58:12 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06160; Fri, 9 Nov 90 09:58:12 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 9 Nov 90 09:57 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA28203; Fri, 9 Nov 90 08:55:35
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 9 Nov 90 09:57 MST
Date: 9 Nov 90 16:42:27 GMT
From: cme!cam!koontz@uunet.uu.net
Subject: RE: What are ICONS?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <08CE390FA6B9A046CE@Arizona.edu>
Message-Id: <5726@alpha.cam.nist.gov>
Organization: National Institute of Standards & Technology, Gaithersburg, MD
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
References: <2219@ac.dal.ca>
Icon has two meanings in the computer context, neither having anything to
do with the Black Virgin of Kiev.
1) In the context of this newsgroup it is a programming language called
Icon. Icon is a descendent of SNOBOL, but emphasizes the succeed/fail
attribute of programming language statements in SNOBOL, rather than
the pattern matching application per se.
2) More generally, an icon is a representation of a file or process in
certain graphics-based user interfaces. You click on the icon with your
mouse to get a menu of things that you can do to the file or with the
application. For example, suppose that you are conducting a terminal
session in a window. You can reduce the window to an icon (perhaps a
picture of a terminal), and stick it in the corner of your screen while
you do something else. Later you can click on the icon to get a menu that
includes the option of converting the icon back into a window in which
there is a terminal session.
From goer%sophist@gargoyle.uchicago.edu Fri Nov 9 10:28:38 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA08389; Fri, 9 Nov 90 10:28:38 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Fri, 9 Nov 90 10:28 MST
Received: by gargoyle.uchicago.edu from sophist.uchicago.edu (5.59/1.14) id
AA07751; Fri, 9 Nov 90 11:27:56 199
Received: by sophist (4.1/UofC3.1X) id AA19459; Fri, 9 Nov 90 11:31:24 CST
Resent-Date: Fri, 9 Nov 90 10:28 MST
Date: Fri, 9 Nov 90 11:31:24 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: what are icons
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <08C9F83D3F79A045C3@Arizona.edu>
Message-Id: <9011091731.AA19459@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.EDU
Please forgive me, all those who are knowledgeable, but what are icons
as applied to computers. I know that they are in plain 'ol English, but what
are they and what kind of system do they run on?
No flames please, I might just go and slit my wrists.
Before you do that, make sure to donate some blood to your local hospital,
where it is probably badly needed.
Seriously, though, here's an brief answer to your question: Icons, as used
in relatively recent computer lingo, refer to symbols on your computer screen
that, when activated in one way or another, function in a way that bears some
analogy to their form. For instance, what do you think activating a picture
of a trash can does? Sure: It trashes something.
Anyway, you have just posted to the Icon group, a mailing list dedicated to
discussion of the Icon programming language. It's got nothing to do with
those cute pictures on your computer screen (if, that is, you are working
with a windowing system that has them). Icon is the successor to Snobol4,
and is used by people for general programming tasks, especially those in-
volving heuristic "algorithms," symbol manipulation, and anything to do
with language and text. It's especially popular among people involved in
nonnumeric computing (in my case, the study of ancient languages).
I hope you don't find this response cause to slit your wrists, by the way.
(Maybe you need to develop a bit thicker skin....)
-Richard
From nowlin@iwtqg.att.com Fri Nov 9 15:42:56 1990
Message-Id: <9011092242.AA24842@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA24842; Fri, 9 Nov 90 15:42:56 -0700
From: nowlin@iwtqg.att.com
Date: Fri, 9 Nov 90 15:22 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: att!cs.arizona.edu!icon-group
Subject: MS-DOS Problem
Here's a message I'm passing along for a friend. He's having a problem
with Icon on MS-DOS and it doesn't have anything to do with memory this
time! Any help would be appreciated.
===========================================================================
I think I've tripped on an honest to goodness bug in MS-DOS Icon for
Version 8. I've been wrong on things like this before but here's what I
found last night.
I am reading in a PC-FILE database and processing it with V8 of Icon on an
AT&T 6300+ MS-DOS compatible computer. The file is not too long - about
5000 bytes. I start by reading in a number of fixed length (32 byte)
header records until I get to a record that starts with a newline
character.
Normally it would read 20-30 such 32-byte records. But with V8 it read the
first and then the next:
line := reads(fd,32)
returns not 32 characters but just 16 and a subsequent read attempt fails.
I presume with EOF.
A dump of the database file shows that the 49th character is an octal 032
which is the DOS CONTROL-Z or end-of-file marker. What appears to be
happening is that V8 is stopping when it sees that CTL-Z. V7 did not do
this!
The open was like:
fd := open("TESTOFF.DBF","ru") | stop("DBF open failed")
and the open succeeds.
Joe T. Hall
(att!ihlpf!pax)
From pax@pax7300.att.com Fri Nov 9 18:10:49 1990
Date: Fri, 9 Nov 90 18:10:49 -0700
From: pax@pax7300.att.com
Message-Id: <9011100110.AA00524@megaron.cs.arizona.edu>
Received: from att.UUCP by megaron.cs.arizona.edu (5.61/15) via UUCP
id AA00524; Fri, 9 Nov 90 18:10:49 -0700
To: att!cs.arizona.edu!icon-group
Subject: MSDOS V8 reads
Cc: pax@ihlpf.att.com, nowlin@iwtqg.att.com
Icon Trekkies!
Is it possible that Version 8 of Icon on MS-DOS will not read past
an octal 32 with reads???
procedure main()
fd := open("TESTOFF.DBF","ru") | stop("DBF open failed")
while line := reads(fd,32) do {
write("*line=",*line)
}
end
TESTOFF.DBF happens to have an octal 032 in position 49 of the file.
The above program on MS-DOS returns:
*line=32
*line-16
The above program on my UNIX-pc reads continuous 32 byte lines
until it reaches the real end-of-file.
It appears to me that Version 8 of Icon for MS-DOS will not read past
this CTL-Z (octal 032) character.
Joe Hall
From sbw@turing.cse.nau.edu Fri Nov 9 18:52:47 1990
Received: from turing.cse.nau.edu ([134.114.64.4]) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00115; Fri, 9 Nov 90 18:52:47 -0700
Received: by turing.cse.nau.edu (5.64/1.34)
id AA02657; Fri, 9 Nov 90 17:53:05 -0700
Message-Id: <9011100053.AA02657@turing.cse.nau.edu>
From: sbw@turing.cse.nau.edu (Steve Wampler)
Date: Fri, 9 Nov 1990 17:53:04 MST
X-Mailer: Mail User's Shell (7.2.0 10/31/90)
To: icon-group@cs.arizona.edu
Subject: example of function tracing...
A recent Icon Newsletter showed a neat way to trace a builtin
function. The following little package shows how this might
be used conveniently. Briefly, the procedure 'trace_option()'
is passed the argument list to 'main'. The argument '-trace'
turns on general tracing. Arguments of the form '-Ffunction'
turn on tracing of the builtin function 'function', if possible.
I think the comments explain everything else.
Right now, the package only traces functions that I frequently
want to trace, though it is easy to add tracing of others.
---- snip 'traceset.icn' ----
procedure trace_options(args)
local nextarg, arg
#
# Check arguments for tracing parameters
#
# can trace some builtin functions, e.g.:
#
# -Ftab
#
# will trace tab()
#
every arg := !args do {
if map(arg) == "-trace" then
&trace := -1
else if match("-F",arg) then { # trace a built-in function
set_trace(arg[3:0])
}
}
return
end
procedure set_trace(vf)
local traceset, vp
#
# trace the builtin function 'vf', if possible
#
if not find("Version 8",&version) then {
write(&errout,"You are running ",&version,", which doesn't support")
write(&errout," this package. You need version 8.")
stop()
}
# so far, can only trace these (easy to add more)
traceset := set(["any","bal","copy","find","many","move","tab","upto"])
if member(traceset,vf) then {
&trace := -1 # have to also trace all procedures!
vp := vf
vp[1] := map(vp[1],&lcase,&ucase)
variable(vp) :=: variable(vf)
write(&errout, "Calls of '",vf,"' will be traced as calls of '",vp,"'")
}
else
write(&errout, vf, " is not a function that can be traced!")
return
end
procedure Any(cs,s,i,j)
return Any(cs,s,i,j)
end
procedure Bal(cs,cl,cr,s,i,j)
suspend Bal(cs,cl,cr,s,i,j)
end
procedure Copy(cs)
return Copy(cs)
end
procedure Find(s1,s,i,j)
suspend Find(s1,s,i,j)
end
procedure Many(cs,s,i,j)
return Many(cs,s,i,j)
end
procedure Match(s1,s,i,j)
return Match(s1,s,i,j)
end
procedure Move(cs)
suspend Move(cs)
end
procedure Tab(i)
suspend Tab(i)
end
procedure Upto(cs,s,i,j)
suspend Upto(cs)
end
---- snip 'traceset.icn' end ----
--
Steve Wampler
{....!arizona!naucse!sbw}
{sbw@turing.cse.nau.edu}
From icon-group-request@arizona.edu Fri Nov 9 19:01:38 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00530; Fri, 9 Nov 90 19:01:38 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 9 Nov 90 17:11 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03261; Fri, 9 Nov 90 16:05:33
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 9 Nov 90 17:12 MST
Date: 9 Nov 90 22:39:30 GMT
From: julius.cs.uiuc.edu!zaphod.mps.ohio-state.edu!unix.cis.pitt.edu!dsinc!netnews.upenn.edu!msuinfo!midway!iitmax!ed@apple.com
Subject: RE: What are ICONS?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <089190666E99A04A34@Arizona.edu>
Message-Id: <4495@iitmax.IIT.EDU>
Organization: Illinois Institute of Technology
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <2219@ac.dal.ca>, <5726@alpha.cam.nist.gov>
In article <5726@alpha.cam.nist.gov> koontz@cam.nist.gov (John E. Koontz X5180) writes:
> [what does Icon mean?]
>1) In the context of this newsgroup it is a programming language called
> Icon. Icon is a descendent of SNOBOL, but emphasizes the succeed/fail
> attribute of programming language statements in SNOBOL, rather than
> the pattern matching application per se.
One thing I've been wondering, and I've not seen it in the forward to the
Icon book, is WHY is the language named "Icon"?? By the way, as long
as I'm asking, does anyone know how SNOBOL and SPITBOL get thier names...
You know, almost _every_ FORTRAN book mentions that its name comes from
FORmula TRANslation, or BASIC is Beginners All-purpose Symbolic Instruction Code
(or whatever) :-)
--
//==========================================================================\\
|| Ed Federmeyer || Internet: ed@iitMax.iit.edu ||
|| "Unauthorized access is || Bitnet: sysed@iitVax ||
|| strictly unauthorized." || Office: (312) 567-5981 ||
\\==========================================================================//
From sbw@turing.cse.nau.edu Sun Nov 11 10:50:19 1990
Received: from turing.cse.nau.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA08540; Sun, 11 Nov 90 10:50:19 -0700
Received: by turing.cse.nau.edu (5.64/1.34)
id AA04852; Sun, 11 Nov 90 10:49:56 -0700
Message-Id: <9011111749.AA04852@turing.cse.nau.edu>
From: sbw@turing.cse.nau.edu (Steve Wampler)
Date: Sun, 11 Nov 1990 10:49:56 MST
X-Mailer: Mail User's Shell (7.2.0 10/31/90)
To: icon-group@cs.arizona.edu
Subject: Oops, wrong publication...
The description for simple builtin function tracing came from
the Icon Analyst, not the Icon Newsletter. (If you're only
getting the Newsletter, you might look into the Analyst - it
has some neat things in it.)
--
Steve Wampler
{....!arizona!naucse!sbw}
{sbw@turing.cse.nau.edu}
From @s.ms.uky.edu:mtbb83@ms.uky.edu Sun Nov 11 12:22:11 1990
Resent-From: @s.ms.uky.edu:mtbb83@ms.uky.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA10366; Sun, 11 Nov 90 12:22:11 -0700
Received: from e.ms.uky.edu by Arizona.edu; Sun, 11 Nov 90 12:21 MST
Received: from s.ms.uky.edu by g.ms.uky.edu id aa26311; 11 Nov 90 14:16 EST
Resent-Date: Sun, 11 Nov 90 12:21 MST
Date: Sun, 11 Nov 90 14:16:24 EST
From: Dr Jerome Krumpelman <mtbb83@ms.uky.edu>
Subject: Remove name
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <0727C1C63859A05510@Arizona.edu>
Message-Id: <9011111416.aa25042@s.s.ms.uky.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I have enjoyed and learned from receiving the Icon traffic on
*.edu net. However, please remove my name from the list, for now.
Please do not re-send this message over the net, and do not purge
me from the mailed material ( ICON news...).
Thanx -- jk
--
Jerome Krumpelman
mtbb83@ms.uky.edu
{rutgers,uunet}!ukma!ms!mtbb83
CompuServe 70441,2760
From icon-group-request@arizona.edu Mon Nov 12 12:01:41 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28358; Mon, 12 Nov 90 12:01:41 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Mon, 12 Nov 90 12:01 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA07849; Mon, 12 Nov 90
10:57:19 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 12 Nov 90 12:01 MST
Date: 12 Nov 90 07:19:43 GMT
From: castor.ucdavis.edu!f140026@ucdavis.ucdavis.edu
Subject: p/d icon wanted for Macintosh
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <0661772D616780041E@Arizona.edu>
Message-Id: <9266@aggie.ucdavis.edu>
Organization: University of California, Davis
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Hi, I'm looking for an anonymously ftp-able version of Icon that will
run on the Macintosh SE. The back of my Icon book says the University
of Arizona to Tucson has it -- does anyone know if it's ftp-able?
Thanks!
f140026@castor.ucdavis.edu
From MYankowski.BSPO@DOCKMASTER.NCSC.MIL Mon Nov 12 15:31:51 1990
Received: from DOCKMASTER.NCSC.MIL by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA05913; Mon, 12 Nov 90 15:31:51 -0700
Date: Mon, 12 Nov 90 17:27 EST
From: MYankowski@DOCKMASTER.NCSC.MIL
Subject: Icon Analyst
To: icon-group@cs.arizona.edu
Message-Id: <901112222754.543046@DOCKMASTER.NCSC.MIL>
Could someone please provide more information on the ICON Analyst?
Mike DOCKMASTER
From ralph Mon Nov 12 16:02:27 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA07058; Mon, 12 Nov 90 16:02:27 -0700
Date: Mon, 12 Nov 90 16:02:20 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9011122302.AA04186@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Mon, 12 Nov 90 16:02:20 MST
To: MYankowski@DOCKMASTER.NCSC.MIL
Subject: Re: Icon Analyst
Cc: icon-group
The Icon Analyst is a technical newsletter published 6 times a year
by the Icon Project. It is 12 pages, 8.5x11". It covers various
aspects of the Icon programming language, mostly related to programming.
The editors are Ralph E. Griswold and Madge T. Griswold, the same as
for the Icon Newsletter, which features less tehcnical material of a more
topical interest.
The first issue of the Analyst was published in August, 1990. The third issue is
presently being prepared for mailing.
Articles so far have covered "getting started", memory monitoring, benchmarking
expressions, expression evaluation, syntactic pitfalls, program readability,
writing portable programs, string scanning, generators, and so forth. There's
also a regular "programming tips" feature.
A subscription to the Icon Analyst is $25 per year, which includes first-class
postage in the United States, Canada, and Mexico. There is an additional
charge of $10 per year for overseas subscriptions, which are sent by
first-class airmail.
Persons wishing to subscribe should make checks payable to The University
of Arizona and send them to
Icon Project
Department of Computer Science
The University of Arizona
Tucson, AZ 85721
U.S.A.
Mastercard and Visa also are acceptable.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From icon-group-request@arizona.edu Tue Nov 13 14:01:54 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28621; Tue, 13 Nov 90 14:01:54 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 13 Nov 90 14:01 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03231; Tue, 13 Nov 90
13:00:49 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 13 Nov 90 14:01 MST
Date: 12 Nov 90 21:28:19 GMT
From: hpcc05!col!hpldola!hp-lsd!egul@hplabs.hpl.hp.com
Subject: RE: What are ICONS?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <058780800407800E43@Arizona.edu>
Message-Id: <10110001@hp-lsd.COS.HP.COM>
Organization: HP Logic Systems Division - ColoSpgs, CO
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <2219@ac.dal.ca>
an icon is a bitmap, created by either you or by the application shell, that
pictorally represents an application, process, login, ...... whatever,
to which you can jump from the current window. This is usually done via
a mouse. "Clicking" the icon will usually start a script which otherwise you would
have to run or key in manually.
A picture (icon) is worth a thousand words, get it?
From ralph Wed Nov 14 10:34:41 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA17349; Wed, 14 Nov 90 10:34:41 -0700
Date: Wed, 14 Nov 90 10:34:39 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9011141734.AA01002@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Wed, 14 Nov 90 10:34:39 MST
To: icon-group
Subject: Bug in MS-DOS Version 8 Icon
As noted in recent icon-group mail, there is a bug in the first release
of Version 8 Icon for MS-DOS. The bug is that the "untranslated"
mode of input/output doesn't work -- input/output always is in the translated
mode.
This means that if you're reading a "binary" file carriage-return/line-feed
combintations get turned into line-feeds on input and conversely on output.
That's not so bad, as long as you're not examining or changing the file inside
an Icon program. Much worse is that a control-Z character (hex 1A) terminates
input.
Note that this is a problem only if you're doing input/output on binary
files. It does not affect input/output on text files.
We corrected this problem a couple of months ago and diskettes distributed
after mid-September have the correction. If you got Version 8 MS-DOS Icon
diskettes from us, check the date on ICON.ARC on the second diskette. If it's
before September 16, 1990, it has the bug.
We've only recently updated our FTP and RBBS files for MS-DOS Icon, so
if you got MS-DOS Icon from us electronically, you probably have a version
with the error.
If this bug is likely to bother you, you can download the corrected version.
If you purchased MS-DOS Icon diskettes from us, send back the second
diskette (DE.2) and we'll send you a free replacement.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From icon-group-request@arizona.edu Wed Nov 14 13:08:29 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA25496; Wed, 14 Nov 90 13:08:29 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Wed, 14 Nov 90 13:07 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA04770; Wed, 14 Nov 90
12:08:00 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 14 Nov 90 13:08 MST
Date: 14 Nov 90 02:11:45 GMT
From: usc!zaphod.mps.ohio-state.edu!unix.cis.pitt.edu!dsinc!netnews.upenn.edu!vax1.cc.lehigh.edu!lehigh.bitnet!GB03@ucsd.edu
Subject: RE:RE: WHAT ARE ICONS
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <04C5CDEDB927801349@Arizona.edu>
Message-Id: <13119021:11:45GB03@lehigh.bitnet>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
@bitnet@lehigh@gb03
It might interest most people to know that BASIC was originally BASIC.
Kemeny and Kurtz got tired of telling people it was only BASIC. No one
believed the inventors. They finally came up with Beginners All
Purpose Simplified Code
Ain't history wunderful!?
From ralph Wed Nov 14 14:57:24 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA01067; Wed, 14 Nov 90 14:57:24 -0700
Date: Wed, 14 Nov 90 14:57:22 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9011142157.AA08332@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Wed, 14 Nov 90 14:57:22 MST
To: icon-group
Subject: Language names
To dispel any misconceptions, the name "Icon" for the Icon programming
language is not an acronym nor does it stand for anything. It's just a
name. It seemed appropriate (at the time) -- I recall mentioning that
the language design was somewhat iconoclastic.
Regrettably, we couldn't see the future and the use of the word "icon"
for pictograms to identify functions and objects on computer screens.
This has caused some confusion and misunderstanding -- some folks see
the word "Icon" and expect a programming language for manipulating
Icons. The fact that our selection of the word came first doesn't
help a lot.
Someone asked about the origin of the name SNOBOL4 for an earlier
programming language. SNOBOL4 is an acronmyn (of sorts) for StriNg
Oriented symBOic Language. We were intending to poke fun at the
way acronyms for programming languages were derived. But no one
thought it was funny.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From icon-group-request@arizona.edu Wed Nov 14 16:26:46 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA05411; Wed, 14 Nov 90 16:26:46 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Wed, 14 Nov 90 16:26 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA10416; Wed, 14 Nov 90
15:18:20 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 14 Nov 90 16:26 MST
Date: 14 Nov 90 22:36:09 GMT
From: usc!elroy.jpl.nasa.gov!suned1!zaft@ucsd.edu
Subject: RE: p/d icon wanted for Macintosh
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <04AA1C182A27801BD1@Arizona.edu>
Message-Id: <6070@suned1.Nswses.Navy.MIL>
Organization: NSWSES, Port Hueneme, CA
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <9266@aggie.ucdavis.edu>
In article <9266@aggie.ucdavis.edu> f140026@castor.ucdavis.edu () writes:
>Hi, I'm looking for an anonymously ftp-able version of Icon that will
>run on the Macintosh SE. The back of my Icon book says the University
>of Arizona to Tucson has it -- does anyone know if it's ftp-able?
>Thanks!
Well, you can FTP to cs.arizona.edu to try to find it; but to the
best of my knowledge (correct me if I'm wrong!) the only version of Icon
available for the Mac is ProIcon, which is NOT shareware, but is supposed
to be inexpensive and very spiffy.
Anyone else have more info?
[Arizona slaughters ASU 11/24! Nine will be fine ! :-)]
--
+ Gordon Zaft | zaft@suned1.nswses.navy.mil +
+ NSWSES, Code 4Y33 | suned1!zaft@elroy.jpl.nasa.gov +
+ Port Hueneme, CA 93043-5007 | Phone: (805) 982-0684 FAX: 982-8768 +
++++ Ubi caritas et amor, Deus ibi est.++++
From ralph Wed Nov 14 16:44:02 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06158; Wed, 14 Nov 90 16:44:02 -0700
Date: Wed, 14 Nov 90 16:44:00 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9011142344.AA11247@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Wed, 14 Nov 90 16:44:00 MST
To: icon-group
Subject: Icon for the Macintosh
To clarify the situation, there is a public-domain version of Icon
available from the Icon Project, but it is not a stand-alone
application and requires the MPW to run. MPW is a subsystem for
the Macintosh that vaguely resembles UNIX. Running Icon under MPW
is similar to running Icon under UNIX -- a command-line environment
without the usual graphical interface.
ProIcon is a standard Macintosh application that has an integrated
environment with an editor that allows you to write and debug
Icon programs without leaving the application. ProIcon also has
several extensions to Icon, including some capabilities for
manipulating windows and handling dialogs from within a ProIcon
program.
Version 2.0 of ProIcon, which is scheduled for release later this
month, also has an interface to HyperCard XCMDs and XFCNs.
For information about ProIcon, contact:
Catspaw, Inc.
P.O. Box 1123
Salida, CO 81201-1123
719-539-3884
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From icon-group-request@arizona.edu Fri Nov 16 11:25:59 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA21839; Fri, 16 Nov 90 11:25:59 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 16 Nov 90 11:25 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA07705; Fri, 16 Nov 90
10:19:51 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 16 Nov 90 11:25 MST
Date: 12 Nov 90 18:10:25 GMT
From: zodiac!tsommers@rutgers.edu
Subject: RE: MSDOS V8 reads
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <0341CD3AFAE7A00526@Arizona.edu>
Message-Id: <201.273ee591@zodiac.rutgers.edu>
Organization: Rutgers University - Computing Services
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <9011100110.AA00524@megaron.cs.arizona.edu>
In article <9011100110.AA00524@megaron.cs.arizona.edu>, pax@pax7300.att.com writes:
> Is it possible that Version 8 of Icon on MS-DOS will not read past
> an octal 32 with reads???
>
> procedure main()
> fd := open("TESTOFF.DBF","ru") | stop("DBF open failed")
> while line := reads(fd,32) do {
> write("*line=",*line)
> }
> end
>
> TESTOFF.DBF happens to have an octal 032 in position 49 of the file.
>
> The above program on MS-DOS returns:
>
> *line=32
> *line-16
My guess would be that Icon is opening the file in text mode, and that
the particular C compiler used to make Icon treats Control-Z as EOF in
text mode. If Icon just passes the mode string unaltered to the C fopen
(or whatever), then perhaps all that is required is to use the
appropriate binary mode mode string when opening the file.
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Fri Nov 16 20:27:37 1990
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA12222; Fri, 16 Nov 90 20:27:37 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA26271; Fri, 16 Nov 90 22:27:34 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Fri, 16 Nov 90 22:22:54 EST
Date: Fri, 16 Nov 90 20:47:38 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <270675@Wayne-MTS>
Subject: Uses of dynamic typing
As I mentioned in an earlier posting, I'm working on the design of SPLASH,
a Systems Programming Language for Software Hackers. A question came up about
how people use Icon's dynamic typing. In Icon the type of a variable isn't
determined until you assign something to it, and even then it can change.
That's in contrast with other languages of the Algol/Pascal/Ada/C sort, in
which every variable has a declared type.
My question is: how important is this flexibility for Icon programming, and
how do people utilize it? There's one place where it clearly pays off: the
possibility of writing a procedure that prints its argument no matter what the
type of the argument. The fact that you can't write the C printf function in
standard C shows why you want this. But aside from printing arguments and
writing out their storage, I haven't been able to think of other operations
that use the flexibility. Interestingly, sorting isn't one of those examples,
since not all data types have a natural ordering relation and even for those
that do, you use different operators in Icon (`<' for numbers, `<<' for
strings.)
Examples, anyone--particularly from programs that do something rather than
just prove something?
Paul Abrahams
abrahams%wayne-mts@um.cc.umich.edu
From gmt Fri Nov 16 21:50:19 1990
Received: from owl.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14316; Fri, 16 Nov 90 21:50:19 -0700
Date: Fri, 16 Nov 90 21:50:18 MST
From: "Gregg Townsend" <gmt>
Message-Id: <9011170450.AA03673@owl.cs.arizona.edu>
Received: by owl.cs.arizona.edu; Fri, 16 Nov 90 21:50:18 MST
To: icon-group
Subject: Re: Uses of dynamic typing
I've used Icon's type flexibility a few times to implement traps in
subroutine packages. The paradigm works like this:
(1) call enable() passing an arbitrary procedure p and other object x
along with whatever is necessary to specify the trap conditions.
(2) when the trap condition occurs -- for example, on every 60th
call to an output routine -- p(x) is called using p and x
from the enable() call. Because x can be any type including
a list or record, any desired amount of data can be passed to p.
This is clumsier in C because instead of an arbitrary object x one must
pass a *pointer* to x, with an appropriate cast, and then access the data
indirectly.
To pick a nit, printf actually can be written in standard C, because the
format specifies the expected types of the remaining arguments and there
are standard routines for retrieving them. There are other problems such
as a danger that getc() has been replaced, but they're irrelevant to this
discussion.
Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
+1 602 621 4325 gmt@cs.arizona.edu 110 57 16 W / 32 13 45 N / +758m
From gudeman Sat Nov 17 01:01:50 1990
Date: Sat, 17 Nov 90 01:01:50 -0700
From: "David Gudeman" <gudeman>
Message-Id: <9011170801.AA19991@megaron.cs.arizona.edu>
Received: by megaron.cs.arizona.edu (5.61/15)
id AA19991; Sat, 17 Nov 90 01:01:50 -0700
To: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
Cc: icon-group@cs.arizona.edu
In-Reply-To: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu's message of Fri, 16 Nov 90 20:47:38 EST <270675@Wayne-MTS>
Subject: Uses of dynamic typing
One important use of dynamic typing is that the type itself gives
some information. I write functions all the time where I _usually_
want a return value of a certain type, but on exceptional conditions I
want something different. For example
# factorial(i) return the factorial of i if i > = 0,
# otherwise return &null.
You can get much the same effect with exception handlers, but it has a
different flavor.
Another use is in program developement. The ability to assign
different types to variables lets you try things out with fewer
changes to a program. At least I think so. Two other features that
help in this are polymorphism and automatic type conversions. Since
Icon has all three, it is hard to say exactly which feature or set of
features is most involved in this.
Incidentally, there is no reason that run-time typing and static
typing can't peacefully coexist in the same language. I can see two
different ways of doing this: the first way is to say that all
variables are untyped. This dynamically typed language also has type
declarations that restrict the types that can be assigned to a given
variable _at run time_. However, a given implementation _may_ give
errors at compile time if a given path might lead to a type conflict.
Furthermore, the implementation may optimize variables that always
have a known type.
The other way is to say that the language is statically typed, but
that there are union types that carry type information around as a
part of the union value. Also, all operators are overloaded so that
they operate on the union types by checking the type at run time and
doing the right operation. There is a specially named union type
"any" that is a union of all other types. One might define that the
default type of a variable is "any".
Both of these paradigms allow the expressiveness of dynamic typing and
the security and efficiency of static typing. In such a language, you
can do developement with dynamic types and then "optimize" the program
by declaring the types of most of the variables.
From ralph Sat Nov 17 06:36:19 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00227; Sat, 17 Nov 90 06:36:19 -0700
Date: Sat, 17 Nov 90 06:36:15 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9011171336.AA22105@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Sat, 17 Nov 90 06:36:15 MST
To: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
Subject: Re: Uses of dynamic typing
Cc: icon-group
I disagree with your characterization of types and variables in Icon. It's not
that a variable doesn't have a type until an assignment is made to it, but
rather that variables are not typed, but values are. Note that every variable
has the null value initially.
I realize this distinction may seem a bit strange to persons who are used
to languages like Pascal, but if you look at the implementation of Icon,
you'll see that's exactly what's going on. A variable is simply a place
to store a value, all variables are the same size, as are all values. All
values carry an identifying type.
As to the usefulness of non-types variables, in my experience, it's mostly
in heterogeneous structures. The elements of a list, for example, are
variables. They can have different types in the same list. Heterogeneous
structures occur frequently in Icon programs. I believe the second edition
of the Icon Programming Language points out examples.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Sat Nov 17 14:08:43 1990
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA12907; Sat, 17 Nov 90 14:08:43 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA25821; Sat, 17 Nov 90 16:08:38 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Sat, 17 Nov 90 16:03:27 EST
Date: Sat, 17 Nov 90 15:45:32 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <270830@Wayne-MTS>
Subject: Dynamic typing revisited
Thanks to all for your replies to my query on this subject.
Re Ralph's comment: yes, I was being sloppy in saying that the type of a
variable can change. Viewing variables as untyped containers of arbitrary
values is both cleaner and and the correct depiction of reality.
Yes, you can use Icon's flexible typing structure to construct heterogeneous
lists. But what isn't clear to me is what such lists are good for, particu-
larly when they contain values of truly arbitrary types rather than of
related types.
In SPLASH I have a `box' type that can designate variables of any type. That
provides an escape from strong typing---the second approach that Dave Gudeman
suggested. I'm still wrestling with the semantics of boxes, though. What
prompted my query was wondering what operations you might want on a box in
addition to the image operation (in the sense of the Icon `image' procedure).
In particular, the image operation would suffice for the trapping that Gregg
gave as an example.
You might think that an obvious operation on boxes would be to get a string
giving the type of the box. But that turns out to be remarkably difficult in
the presence of recursive types. That problem doesn't come up in Icon
because Icon doesn't have recursive types---with dynamic typing, you don't
need them.
To clarify: in Pascalish languages you can have something like:
type t is record v: integer; link: ref t end
How then would you display the definition of t in a form that id independent
of the name you give the type? In Icon the type would simply be `t' (which
actually isn't very revealing if you don't have the definition of `t' handy).
By the way, Modula-3 has a `refany' type which provides an escape from strong
typing in that language. But you can only dereference a `refany' value using
a `typecase' construction, which forces you to enumerate all the
possibilities. That's less general than being able to apply `image' without
knowing the type.
Paul
abrahams%wayne-mts@um.cc.umich.edu
From nowlin@iwtqg.att.com Sat Nov 17 15:02:49 1990
Message-Id: <9011172202.AA14204@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14204; Sat, 17 Nov 90 15:02:49 -0700
From: nowlin@iwtqg.att.com
Date: Sat, 17 Nov 90 15:39 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: att!cs.arizona.edu!icon-group
Subject: Re: Uses of dynamic typing
> than just prove something?
I have three specific examples. The first is the use of the types "null"
and "file" in programs that can read input from files or from standard
input. The same expressions can be used for input if the variable used as
a file is set to &null when reading from standard input. I've used this
many times. The same kind of scheme can be used for output.
The second example is a set of procedures that does regular expression
matching. It uses a list of records. Each record contains a pair of
values; a procedure and an argument to be passed to the procedure.
Sometimes the argument is a string, sometimes it's a cset, and sometimes
it's &null. Icon doesn't care which I store as the second value in the
record.
The third use is a set of procedures I wrote for a friend. These
procedures allow a series of global variables to be dumped into a file. A
complementary set of procedures can read the dump file and reconstruct the
global variables with the same values as the program that dumped them.
These procedures are used to chain together a series of programs. This
would require a whole series of different variables if Icon didn't allow me
to use the same variable over and over with different types each time.
Very handy.
As a side note we've just recently achieved a breakthrough at work (AT&T)
and we're now allowed to use Icon for "real" projects. It's great. Our
methodology calls for code inspections and those of us who are familiar
with Icon initially thought Icon would be much easier to code inspect than
C++ or C. WRONGO! The tie in to this subject is that dynamic typing may
contribute to the problem. It just seems counter intuitive that Icon would
be harder to inspect but after our initial session that was definitely my
impression. I'll try to figure out why on my own but if anyone has any
ideas throw them out.
Jerry Nowlin (iwtqg!nowlin)
From nowlin@iwtqg.att.com Sat Nov 17 15:02:53 1990
Message-Id: <9011172202.AA14215@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14215; Sat, 17 Nov 90 15:02:53 -0700
From: nowlin@iwtqg.att.com
Date: Sat, 17 Nov 90 15:51 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: att!cs.arizona.edu!icon-group
Subject: Re: Dynamic typing revisited
> ...
> How then would you display the definition of t in a form that is
> independent of the name you give the type? In Icon the type would
> simply be `t' (which actually isn't very revealing if you don't have
> the definition of `t' handy).
> ...
>
> Paul
In fact, type 't' from Icon isn't that bad for some applications. You can
get the fact that type 't' is a record by looking at the image() and then
you can just treat values of 't' like lists and generate the members or
directly subscript them. I don't know how you'd find the specific member
names but you can get at the member values and that's more important in
most cases.
Jerry Nowlin (iwtqg!nowlin)
From att!arizona!wgg@cs.washington.edu Sat Nov 17 15:37:18 1990
Received: from att.UUCP by megaron.cs.arizona.edu (5.61/15) via UUCP
id AA15114; Sat, 17 Nov 90 15:37:18 -0700
Received: from june.cs.washington.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14976; Sat, 17 Nov 90 15:30:40 -0700
Received: by june.cs.washington.edu (5.64/7.0jh)
id AA16599; Sat, 17 Nov 90 14:30:35 -0800
Date: Sat, 17 Nov 90 14:30:35 -0800
From: wgg@cs.washington.edu (William Griswold)
Return-Path: <wgg@cs.washington.edu>
Message-Id: <9011172230.AA16599@june.cs.washington.edu>
To: att!cs.arizona.edu!icon-group, nowlin@iwtqg.att.com
Subject: Re: Uses of dynamic typing
Re: Jerry Nowlin's message
>As a side note we've just recently achieved a breakthrough at work (AT&T)
>and we're now allowed to use Icon for "real" projects. It's great. Our
>methodology calls for code inspections and those of us who are familiar
>with Icon initially thought Icon would be much easier to code inspect than
>C++ or C. WRONGO! The tie in to this subject is that dynamic typing may
>contribute to the problem. It just seems counter intuitive that Icon would
>be harder to inspect but after our initial session that was definitely my
>impression. I'll try to figure out why on my own but if anyone has any
>ideas throw them out.
>
To me this suggests that a language in which you could add typing information
during later phases of a project would be valuable. Having a tool
to infer the types and insert them for you would be great, and could be
revealing in itself. In the presence of tools like Ken Walker's Icon compiler,
this doesn't sound impractical.
This type information serves as constructive comments in the code. Not
only does it tell a new programmer what is going on, but type violations
created by the programmer's changes to the code will signal that the changes
are outside the intents of the original implementation.
bill
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Sun Nov 18 16:36:41 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03210; Sun, 18 Nov 90 16:36:41 -0700
Received: by uwm.edu; id AA23452; Sun, 18 Nov 90 09:06:31 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Sun, 18 Nov 90 08:01:12 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Sun, 18 Nov 1990 07:13 CDT
Date: Sun, 18 Nov 1990 07:13 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Re: Uses of dynamic typing
To: icon-group@cs.arizona.edu
Cc: icon-group@cs.arizona.edu
Message-Id: <2D4AF1A400600126@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu,
Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
X-Vms-To: IN%"Paul_Abrahams%Wayne-MTS@um.cc.umich.edu"
X-Vms-Cc: IN%"icon-group@cs.arizona.edu"
Regarding: Uses of dynamic typing
> ... text ...
> My question is: how important is this flexibility for Icon programming, and
> how do people utilize it?
>
> ... text ...
>
> Examples, anyone--particularly from programs that do something rather than
> just prove something?
>
> Paul Abrahams
> abrahams%wayne-mts@um.cc.umich.edu
Some things are implicitly utilized. Dynamic typing, in my opinion, causes
some things.
1. Reduces lines of code, since many variable type declarations become
un-necessary.
2. Reduces code clutter from having to cast this type to that in expressions.
Although I still find it necessary for floating point calculations.
3. I suppose I'm just a lazy programmer, and when programming in Icon, I'm
not fighting the datatypes. I just code away, much like I did when BASIC
was my native computer language.
4. No need for separate sets of procedure libraries. Well, I suppose if well
designed, C & Pascal can have smart procedures that adapt to the type of
data passed.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Mon Nov 19 06:27:14 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00165; Mon, 19 Nov 90 06:27:14 -0700
Received: by uwm.edu; id AA09863; Mon, 19 Nov 90 07:27:02 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Mon, 19 Nov 90 06:55:13 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Mon, 19 Nov 1990 06:19 CDT
Date: Mon, 19 Nov 1990 06:19 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Card game algorythms
To: icon-group@cs.arizona.edu
Message-Id: <EEE17FFF40600175@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
I've been thinking about card game algorythms. It seems to me that cards
belong in a set rather than a list. Each hand would also be a set. Since
order in a set is arbitrary, I become a little confused as to shuffling
the deck. And even if one were to use lists, shuffling is an operational
remnant of our physical world. In a computer, virtual shuffling could
just consist of dealing cards from random deck positions.
Is there one basic shuffling concept, or are there several approaches?
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Mon Nov 19 08:21:57 1990
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03820; Mon, 19 Nov 90 08:21:57 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA09475; Mon, 19 Nov 90 10:21:49 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Mon, 19 Nov 90 10:17:21 EST
Date: Sun, 18 Nov 90 22:36:28 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <270978@Wayne-MTS>
Subject: Dynamic typing (more)
To respond to various points:
(1) Finding a representation of dynamic types is more difficult when (a) the
types involve mutual recursions, not just one, and (b) your language has
structural equivalence rather than name equivalence (like Modula-3).
Structurally equivalent types should have the same representation even if
their declarations use different names. In fact, it's an interesting job
for an Icon program (given, say, a textual representation of a collection of
Modula-3 type declarations).
(2) Of Jerry Nowlin's three examples, the one I find most interesting is the
third, in which global variables of arbitrary types are dumped to a file and
read back in again by another program (or another execution of the same
program, I gather). The first two could be done with variant records,
subclasses, or what have you since there are only a small, finite number of
choices. The third one involved a kind of inverse of `image' that
transforms an image into a value for almost any type at all (but not for
procedures, I'd guess).
(3) My box type in SPLASH isn't overloaded in the sense that x+y adds x and
y even if x and y are boxes containing numbers. It will probably have an
extraction operator that extracts the variable or value contained in a box,
but I haven't figured out how to do this because I only want to permit the
extraction in a context where the type of the box's contents has been
proclaimed (using something like the Modula-3 TYPECASE statement). But
TYPECASE doesn't work well when you have complex nested types.
(4) There isn't a necessary connection between compile-time typing and
operator overloading, but languages with dynamic typing generally don't seem
to have operator overloading except in the weak sense of things like
overloading + to work both on integers and reals. In fact, Icon probably
could have been designed to use overloading more extensively and even to
make it available to users, with type declarations used in parameter lists
solely for the purpose of overload resolution. Then you wouldn't have
different operators for lexical versus numerical comparison. I won't try to
argue very strongly that it would be better that way, but it's an
interesting possibility that as far as I know no language designers have
considered.
(5) I probably should reiterate that a lot of the design of SPLASH was
inspired by Icon, and SPLASH has a lot of Icon features in it (especially
the central notions of generators and of failure as a possible outcome of
expression evaluation). The current state of it is that the definition is
about 50 pages long and, I'd estimate, about 60% complete (which doesn't
imply that the final version will be 80 pages long).
Paul
abrahams%wayne-mts@um.cc.umich.edu
From gudeman Tue Nov 20 13:09:12 1990
Date: Tue, 20 Nov 90 13:09:12 -0700
From: "David Gudeman" <gudeman>
Message-Id: <9011202009.AA14193@megaron.cs.arizona.edu>
Received: by megaron.cs.arizona.edu (5.61/15)
id AA14193; Tue, 20 Nov 90 13:09:12 -0700
To: icon-group@cs.arizona.edu
In-Reply-To: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu's message of Sun, 18 Nov 90 22:36:28 EST <270978@Wayne-MTS>
Subject: Dynamic typing (more)
>Date: Sun, 18 Nov 90 22:36:28 EST
>From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
>Structurally equivalent types should have the same representation even if
>their declarations use different names.
Hmm, that really isn't obvious to me. If I declare two structurally
equivalent types with different names, then I probably have some
reason for wanting to distinguish them. In this case I would rather
have the representations include the names explicitely. Of course, if
type equivalence isn't the same as representation equivalence then I
would also want a predicate on representations to tell me when two
representations denote the same type.
>...The first two could be done with variant records,
>subclasses, or what have you since there are only a small, finite number of
>choices...
But what "could be done" isn't the issue. Obviously you can do
anything in Pascal that you can do in Icon, the issue is how easy it
is to do and how easy it is to understand. Typing in a list of
different things to do for different types is more cumbersome than
letting the language figure it out. Strict static typing in this
sense violates one of my cardinal rules of language design: "Make the
computer do any work that it can. The programmer should only be
required to do what the computer can't."
>(3) My box type in SPLASH isn't overloaded in the sense that x+y adds x and
>y even if x and y are boxes containing numbers.
In this case, I would say that the box type does not give you the
advantages of dynamic typing at all. It is just an abbreviation for a
union of everything. Incidentally, in the union approach to dynamic
typing (that is, unions-with-type-information and universal
overloading) the operators should be overloaded on all unions. For
example if
union int_or_string {int, string}
declares a new type "int_or_string", and I declare variables "x" and
"y" of this type, then the expression "x + y" should be understood to
do the correct thing based on the dynamic types of "x" and "y". In
other words, there is no reason to limit this overloading to unions of
everything.
>(4) There isn't a necessary connection between compile-time typing and
>operator overloading, but languages with dynamic typing generally don't seem
>to have operator overloading except in the weak sense of things like
>overloading + to work both on integers and reals...
Icon has two ways in which an operator can work on different types:
automatic conversion and overloading. There is actually quite a bit
of overloading, look at unary "!" and "?", subscripting, sectioning,
general comparisons ("===" and friends), member(), sort(), and copy().
The comparison operators could not be overloaded without losing some
functionality. They are currently defined to do automatic type
conversions, which has different uses.
From icon-group-request@arizona.edu Thu Nov 22 06:25:36 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA11121; Thu, 22 Nov 90 06:25:36 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 22 Nov 90 06:25 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA00781; Thu, 22 Nov 90
05:25:07 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 22 Nov 90 06:25 MST
Date: 20 Nov 90 06:25:31 GMT
From: news@psuvax1.cs.psu.edu
Subject: RE: Card game algorythms
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FEB4C1A24D9DA04D3D@Arizona.edu>
Message-Id: <Fe+tb1a3@cs.psu.edu>
Organization: Penn State Computer Science
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <EEE17FFF40600175@mis.mcw.edu>
Each hand is a set, but the deck itself is a list. If you consider
solitaire games, then the various piles, the talon, and the stock are
all lists. I've wanted a generalized solitaire language for a while..
--
Felix Lee flee@cs.psu.edu
From icon-group-request@arizona.edu Thu Nov 22 08:41:49 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA16629; Thu, 22 Nov 90 08:41:49 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 22 Nov 90 08:41 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA06651; Thu, 22 Nov 90
07:28:01 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 22 Nov 90 08:41 MST
Date: 21 Nov 90 02:43:46 GMT
From: iris!hildum@ucdavis.ucdavis.edu
Subject: Icon I/O system and X Windows/Motif
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FEA1BA85254DA03AB8@Arizona.edu>
Message-Id: <7999@ucdavis.ucdavis.edu>
Organization: U.C. Davis - Department of Electrical Engineering and Computer
Science
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I have been looking at some articles on the X window system recently,
and am curious about the Icon communities' thoughts on how an X
Window/Motif based graphical interface would most naturally be
incorporated. I realize that the intent of Icon is the development of
high level language constructs and semantics; however, with the growing
importance of graphical interfaces, the current simple I/O system Icon
supports seems inadequate.
In particular, I am interested in the the effects of language
constructs and semantics such as coexpressions, suspend and resume,
generators, and failure in combination with the asynchronous model of
the X protocol.
Any comments on how such an interface might be built and what form it
should take?
dehildum@ucdavis.ucdavis.edu (Internet)
dehildum@ucdavis.bitnet (BITNET)
ucbvax!ucdavis!dehildum (uucp)
From icon-group-request@arizona.edu Fri Nov 23 18:29:56 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA13934; Fri, 23 Nov 90 18:29:56 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 23 Nov 90 18:29 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA13064; Fri, 23 Nov 90
17:24:52 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 23 Nov 90 18:29 MST
Date: 23 Nov 90 20:54:07 GMT
From: usc!bbn.com!nic!chaos.cs.brandeis.edu!iad@rutgers.edu
Subject: Help/hint needed
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FD8666DAE9FDA05941@Arizona.edu>
Message-Id: <1990Nov23.205407.4570@chaos.cs.brandeis.edu>
Organization: Brandeis University Computer Science Dept
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
SOS!
I've been only using Icon for about four weeks, and I'm enjoying it
more than I can tell. However, today I ran into the following problem:
I was trying to write a procedure that takes a list of coexpressions
(its length must be allowed to vary) and suspends lists of the
corresponding values of the arguments. For example, the call
f ([create 1 to 3, create "Q" | "Z"])
would produce the result sequence
{ [1,"Q"], [1,"Z"], [2,"Q"], [2,"Z"], [3,"Q"], [3,"Z"] }.
I thought is should be easy (given the overall power of Icon), but
somehow I can't think of any way of doing it without recursion. Can
anyone give me a hint?
Thanks,
Ivan A. Derzhanski
P.S. My apologies if it turns out to be actually very simple.
--
Ivan A. Derzhanski iad@chaos.brandeis.edu
MB 1766 Brandeis University P.O.Box 9110 Waltham, MA 02254-9110
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Mon Nov 26 08:50:06 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02332; Mon, 26 Nov 90 08:50:06 -0700
Received: by uwm.edu; id AA20516; Mon, 26 Nov 90 09:49:54 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Mon, 26 Nov 90 09:34:07 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Mon, 26 Nov 1990 08:55 CDT
Date: Mon, 26 Nov 1990 08:54 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Icon in Windowing environments
To: icon-group@cs.arizona.edu
Message-Id: <84CC7215C06007E3@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Icon seems to be designed around the data stream concept of the unix shell
(character cell) environment. It's not not fast enough with image processing.
I've tried it.
Still, here is some thinking from the keyboard. I won't mention any new
language constructs that may be needed to support it. I'm just going over
the most external look and feel of what an X-Window/Motif Icon
environment might look like ...
Obviously, with a windowing interface the term 'icon' becomes overloaded. To
preserve the 'Icon' language we'd call the pictures objects or pix to keep
the names straight. These objects will have a file name squeezed into them,
and a user editable pictogram to make it more recognizable. Each file type,
should have special distinguishing features to make them instantly
recognizable. icont may be another object to which source and ucode is fed,
and new icode objects generated.
Files : (Source)
These contain icon source code. Clicking on a source object brings
them up in an editor window of choice.
(Ucode)
These contain the intermediate ucode. An IPATH window contains ones
that one may want to link with.
(Icode exec)
Under unix these can be made self-starting. I'm not sure what to do
about other operating systems. This graphical object would have input
and output sockets (stdin & stdout always by default, others declared
in the program). Data files have only a stdin/stdout socket pair,
where icode files can have many sockets. These sockets should have
'gender' and allow one to construct applications much like LEGO
blocks.
(Data files (pipes))
These are data files or other shell filters. The icon environment
would give them each a stdin/stdout socket pair. If the object is
a textual data file, clicking on it should pop it into an editor
window just like source code.
These are just some food for thought. I come from a VAX VMS VT100 style shop
with a few PCs and MACs laying around, so my vision may be clouded by
ignorance.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Mon Nov 26 08:50:21 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02366; Mon, 26 Nov 90 08:50:21 -0700
Received: by uwm.edu; id AA20522; Mon, 26 Nov 90 09:50:09 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Mon, 26 Nov 90 09:34:22 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Mon, 26 Nov 1990 09:18 CDT
Date: Mon, 26 Nov 1990 09:17 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: final language construct
To: icon-group@cs.arizona.edu
Message-Id: <87FEAFB0806007E3@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Icon is a pretty nifty programming language. I like and use the 'initial'
construct. But sometimes I wished I had a 'final' construct. This may be
a crummy example, but it illustrates the concept of the final pass through
a procedure. Perhaps this isn't even implementable? Any comments on it's
usefullness or implementation problems?
procedure print(fo,line)
static ff, pageno, line_count
initial
{
ff := ""
pageno := 0
line_count := 0
}
if (line_count -:= 1) < 0 then
{
write(fo,ff,"title line ",(pageno +:= 1))
line_count := 55
ff := "\f"
}
write(fo,format(line))
final
{
output_summary()
}
end
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From goer%sophist@gargoyle.uchicago.edu Mon Nov 26 13:03:38 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14510; Mon, 26 Nov 90 13:03:38 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Mon, 26 Nov 90 13:02 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA25249; Mon, 26 Nov 90 14:02:47 CST
Received: by sophist (4.1/UofC3.1X) id AA29090; Mon, 26 Nov 90 14:06:04 CST
Resent-Date: Mon, 26 Nov 90 13:03 MST
Date: Mon, 26 Nov 90 14:06:04 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: final, initial
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FB5882BD4C6DA05D84@Arizona.edu>
Message-Id: <9011262006.AA29090@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
In additions to initial clauses, I've often wanted to use second
clauses, thirds, fourths, as well as finals. I guess it could go
on forever. With "finals" the real problem seems to be how the
interpreter is supposed to know that a given call is really the
last one. I don't see how it can know this sort of thing.
-Richard (goer@sophist.uchicago.edu)
From icon-group-request@arizona.edu Mon Nov 26 22:47:58 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06914; Mon, 26 Nov 90 22:47:58 -0700
Received: from UCBVAX.Berkeley.EDU by Arizona.edu; Mon, 26 Nov 90 22:47 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA02485; Mon, 26 Nov 90
21:44:23 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 26 Nov 90 22:47 MST
Date: 27 Nov 90 05:30:22 GMT
From: iris!hildum@ucdavis.ucdavis.edu
Subject: RE: final, initial
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FB06DC0653EDA06F20@Arizona.edu>
Message-Id: <8008@ucdavis.ucdavis.edu>
Organization: U.C. Davis - Department of Electrical Engineering and Computer
Science
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <9011262006.AA29090@sophist>
Two cents worth: probably the only way to do this is to have the
interpreter invoke the final clauses as part of the program
termination. This leads to the following issues:
1. Error termination - are final clauses executed?
2. What order are multiple final clauses executed - the order in which
the procedures were first invoked?
Of course, all this can be handled by placing the appropriate calls at
the "end" of the program, so I am not sure this really helps (other
than grouping code...)
If you are actually trying to execute the code as part of the final
call, I suspect that it cannot be done. It looks suspicously like a
halting problem to me...
Eric
dehildum@ucdavis.ucdavis.edu (Internet)
dehildum@ucdavis.bitnet (BITNET)
ucbvax!ucdavis!dehildum (uucp)
From nowlin@iwtqg.att.com Tue Nov 27 08:49:45 1990
Message-Id: <9011271549.AA28956@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28956; Tue, 27 Nov 90 08:49:45 -0700
From: nowlin@iwtqg.att.com
Date: Tue, 27 Nov 90 08:05 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: icon-group@cs.arizona.edu
Subject: Re: help/hint needed
> Date: 23 Nov 90 20:54:07 GMT
> From: usc!bbn.com!nic!chaos.cs.brandeis.edu!iad@rutgers.edu
> Subject: Help/hint needed
>
> SOS!
>
> I've been only using Icon for about four weeks, and I'm enjoying it
> more than I can tell. However, today I ran into the following problem:
>
> I was trying to write a procedure that takes a list of coexpressions
> (its length must be allowed to vary) and suspends lists of the
> corresponding values of the arguments. For example, the call
>
> f ([create 1 to 3, create "Q" | "Z"])
>
> would produce the result sequence
>
> { [1,"Q"], [1,"Z"], [2,"Q"], [2,"Z"], [3,"Q"], [3,"Z"] }.
>
> I thought is should be easy (given the overall power of Icon), but
> somehow I can't think of any way of doing it without recursion. Can
> anyone give me a hint?
>
> Thanks,
>
> Ivan A. Derzhanski
>
> P.S. My apologies if it turns out to be actually very simple.
> --
> Ivan A. Derzhanski iad@chaos.brandeis.edu
> MB 1766 Brandeis University P.O.Box 9110 Waltham, MA 02254-9110
Admittedly coexpressions are not a piece of Icon I use much. I can't think
of a way to do this with coexpressions without recursing either. But I
stopped and asked my self why should I use coexpressions if what I want is
all the possible combinations of a list of generators? Maybe the example
you used was oversimplifying your problem but the following program
generates the sequences you asked for without even requiring a procedure:
procedure main()
every l :=
[1 to 3, "Q" | "Z"]
do {
writes("[ ")
every writes(!l," ")
write("]")
}
end
This isn't the normal coding style I'd use but it isolates the piece of
code that's pertinent to the original question. To make this more general
you can use a procedure but it's a simple procedure. The following is the
same basic program but with a procedure call. The key is to use a list of
generators instead of a list of coexpressions. I just prefer to simplify.
procedure main()
every l :=
f( [1 to 3, "Q" | "Z"] )
do {
writes("[ ")
every writes(!l," ")
write("]")
}
end
procedure f(lg)
suspend lg
end
This seems almost too easy so if I've really missed the point please let me
know. Otherwise, isn't Icon great!
Jerry Nowlin
(att!iwtqg!nowlin)
From nowlin@iwtqg.att.com Tue Nov 27 08:49:53 1990
Message-Id: <9011271549.AA28965@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28965; Tue, 27 Nov 90 08:49:53 -0700
From: nowlin@iwtqg.att.com
Date: Tue, 27 Nov 90 08:59 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: icon-group@cs.arizona.edu
Subject: Re: hints...
> procedure main()
>
> every l :=
>
> [1 to 3, "Q" | "Z"]
>
> do {
> writes("[ ")
> every writes(!l," ")
> write("]")
> }
>
> end
> ...
>
> This seems almost too easy so if I've really missed the point please let
> me know. Otherwise, isn't Icon great!
Forget the procedure example (not shown). In fact, forget the whole
solution unless you can use constant lists of generators as above.
Rule #1 - When something seems too easy to be true, it is.
The generation that makes this work is driven by goal directed evaluation
in the context of the every. It works the way I thought it did almost but
requires a constant list of generators in that context. If you assign a
list of generators to a variable and use the variable in this construct it
won't generate the result sequence wanted. This requires more thought.
Too bad I have real work to do!
Jerry
From icon-group-request@arizona.edu Tue Nov 27 14:33:40 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA15180; Tue, 27 Nov 90 14:33:40 -0700
Received: from UCBVAX.Berkeley.EDU by Arizona.edu; Tue, 27 Nov 90 14:32 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA21614; Tue, 27 Nov 90
13:21:42 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 27 Nov 90 14:32 MST
Date: 27 Nov 90 17:25:25 GMT
From: ingr!@uunet.uu.net
Subject: RE: WHAT ARE ICONS
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FA82CFE70ACDA06D27@Arizona.edu>
Message-Id: <1805@b15.INGR.COM>
Organization: Intergraph Huntsville
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <13119021:11:45GB03@lehigh.bitnet>
In <13119021:11:45GB03@lehigh.bitnet> GB03@Lehigh writes:
:It might interest most people to know that BASIC was originally BASIC.
:Kemeny and Kurtz got tired of telling people it was only BASIC. No one
:believed the inventors. They finally came up with Beginners All
:Purpose Simplified Code
The American Heritage Dictionary (2nd College Edition, 1985) says:
Beginner's All-purpose Symbolic Instruction Code
From nowlin@iwtqg.att.com Tue Nov 27 20:46:12 1990
Message-Id: <9011280346.AA29841@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29841; Tue, 27 Nov 90 20:46:12 -0700
From: nowlin@iwtqg.att.com
Date: Tue, 27 Nov 90 17:16 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: icon-group@cs.arizona.edu
Subject: Re: final clause
> Icon is a pretty nifty programming language. I like and use the 'initial'
> construct. But sometimes I wished I had a 'final' construct. This may be
> a crummy example, but it illustrates the concept of the final pass through
> a procedure. Perhaps this isn't even implementable? Any comments on it's
> usefulness or implementation problems?
I don't see anyway to implement a final clause. You might have the
interpreter go through all the declared procedures when it's told to
terminate and execute the final clauses. Even then how do you know that
the order of execution of final clauses isn't significant? How would you
handle run time errors or external interrupts?
If that won't work, how could the interpreter possibly know that a
procedure won't be executed again? I don't think procedures ever go out of
scope in Icon so that's not a valid criteria. What happens when you
declare a variable with the same name as a procedure? What happens when a
procedure is assigned to a variable? I don't see any way to do this.
Is this an attempt to get construction and destruction type constructs for
procedures?
> procedure print(fo,line)
> static ff, pageno, line_count
> initial
> {
> ff := ""
> pageno := 0
> line_count := 0
> }
> if (line_count -:= 1) < 0 then
> {
> write(fo,ff,"title line ",(pageno +:= 1))
> line_count := 55
> ff := "\f"
> }
> write(fo,format(line))
> final
> {
> output_summary()
> }
> end
The example above has some problems since the output_summary() procedure is
called as part of the final clause but it isn't passed the parameters that
were initialized in the initial clause. I get the idea though. This could
be handled by making the 'fo' and 'line' parameters optional. If they're
missing invoke the equivalent of the final clause. I use optional
parameters frequently although not usually for this kind of thing.
Jerry Nowlin
(...!att!iwtqg!nowlin)
From djbailey@skyler.mavd.honeywell.com Wed Nov 28 09:51:09 1990
Message-Id: <9011281651.AA25093@megaron.cs.arizona.edu>
Received: from skyler.mavd.honeywell.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA25093; Wed, 28 Nov 90 09:51:09 -0700
Date: 28 Nov 90 10:49:00 CDT
From: "BAILEY, DON" <djbailey@skyler.mavd.honeywell.com>
Subject: Re: final clause
To: "icon-group" <icon-group@cs.arizona.edu>
Has anyone else suggested the simple brute force solution to implementing
a "final" clause? Just push your program down a level in the calling
sequence. For example,
procedure main(args)
#
my_real_program(args,final_parameter_list)
do_final_work(final_parameter_list)
end
The real program can have an initial clause if it really needs it.
Whenever it finishes, "do_final_work" will be called. At worst, you
have to make some extra data global and deal with the success or
failure of your program. This approach lets you invoke different
final processing, by adding an "if", depending on success or failure
or a state variable you pass back up.
-- Don J. Bailey (djbailey@skyler.mavd.honeywell.com)
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Wed Nov 28 13:17:15 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA04749; Wed, 28 Nov 90 13:17:15 -0700
Received: by uwm.edu; id AA10695; Wed, 28 Nov 90 14:16:58 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Wed, 28 Nov 90 14:00:48 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Wed, 28 Nov 1990 13:00 CDT
Date: Wed, 28 Nov 1990 13:00 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: The Final Clause
To: icon-group@cs.arizona.edu
Message-Id: <396C1E3A80400B3F@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Regarding : The Final Clause
I've seen a lot of interesting replies on this problem. Some say it's not
possible because it's 'decidable'. Someone else mentioned the 'halting
problem', which I assume refers to Turing machines. How does a procedure
'know' when it's finally called? Also the example I furnished wasn't very
good, but I can't seem to think of another at the moment. I didn't think
it would have been such a big deal. After all, how does program know when
it's reached the end of file or pipe? (The operating system tells it).
I also thought that since Icon is a virtual machine, that its extensibility
would allow something like the Variant Translator or Personal Interpreter
to handle it.
Practically, though, the method I envisioned was that Icon would do a silent
run, recording activity to a journal (much like MEMMON). Upon exit, the final
clause(s) would be inserted into the journal stream, and then the whole mess
flushed (kind of like a database commit).
I thought about that a bit, and I guessed it would gobble tons of memory/disk
and cause everything to run slow. I also dreaded permutations with 'final's
getting tied up in recursive infinite loops. I also considered limiting it
to one 'final' per program, or allowing only in main(), but that really did
not seem too useful.
I guess the best approach is to use a procedure final() called near the end
of main() using passed or global variables. Thanx for all the ideas.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Sat Dec 1 11:47:20 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA25239; Sat, 1 Dec 90 11:47:20 -0700
Received: by uwm.edu; id AA18340; Sat, 1 Dec 90 12:46:59 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Sat, 1 Dec 90 12:22:02 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Sat, 1 Dec 1990 08:48 CDT
Date: Sat, 1 Dec 1990 08:48 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: A more useful concept
To: icon-group@cs.arizona.edu
Message-Id: <71AFB0BFE0401C1A@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
In the past icon has been getting better and better. For example there's
now a remove(filespec) procedure to delete files which is better than
system("rm "||filespec)
and I think there's also a rename(ofile,nfile) instead of
system("mv "||ofile||" "||nfile)
I think it would be nice to have a few more file management primitives. Oh oh,
maybe they already exist, and I should just read the manual?
cpfile(oldfile,newfile) # copy files
appfile(oldfile,existingfile) # append files together
listvar := dir(path) # generate a list of file names (directory)
freedisk:= df(dspec) # returns number of blocks of free disk
like unix df or vms show dev/mount
----
Also there are the environmental variables that are accessible with
getenv(), and known as logicals to VMS people.
Is it possible to capture aliases (symbols to vms people)? Or doesn't that
sound like a useful enough feature?
From icon-group-request@arizona.edu Tue Dec 4 14:36:50 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA06044; Tue, 4 Dec 90 14:36:50 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Tue, 4 Dec
1990 14:36 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA00435; Tue, 4 Dec 90 13:24:37
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 4 Dec 1990 14:36 MST
Date: 4 Dec 90 19:26:00 GMT
From: timbuk!cs.umn.edu!mmm.serc.3m.com!us269574@uunet.uu.net (Darryn J. Kozak)
Subject: Is ICON the successor to SNOBOL?
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <FDDB0097CC4004B1@Arizona.edu>
Message-Id: <1990Dec4.192600.16430@mmm.serc.3m.com>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: 3M - St. Paul, MN 55144-1000 US
Is ICON the successor to SNOBOL?
Darryn Kozak
3M Center
260-4A-08
St. Paul, MN 55144
phone: 612-733-3271
email: us269574@mmm.3m.com or kozak@umn-cs.edu
FAX: 612-737-3213
From goer%sophist@gargoyle.uchicago.edu Wed Dec 5 10:05:04 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA21479; Wed, 5 Dec 90 10:05:04 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu with PMDF#10282; Wed, 5 Dec
1990 10:03 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA13345; Wed, 5 Dec 90 11:03:29 CST
Received: by sophist (4.1/UofC3.1X) id AA05261; Wed, 5 Dec 90 11:06:47 CST
Resent-Date: Wed, 5 Dec 1990 10:04 MST
Date: Wed, 5 Dec 90 11:06:47 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: Snobol -> Icon
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <A1006ED19C400F44@Arizona.edu>
Message-Id: <9012051706.AA05261@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
(I didn't see anyone else respond, and it seems worthwhile, I'll
try to answer this question. Note that I am not part of the Icon
Project, and that some of what I say may not be entirely accurate
:-)).
Re: Is ICON the successor to SNOBOL?
Sure. They started working on SL5, but suddenly felt inspired with
the knowledge that the backtracking mechanisms found in string scan-
ning could be superimposed on a consistent, general-purpose program-
ming language with a modern, procedurally oriented program struc-
ture. Icon is, at once, like Snobol string processing gone wild, and
at the same time like languages such as C and Pascal. I've also heard
it described as an Algolish Prolog as well, because it essentially im-
plements a backtracking mechanism somewhat like that of Prolog in
terms of control structures we all know and "love." It is not really
quite a *successor* to Snobol, but it is certainly a logical step
forward. I don't believe SL5 (which *would* have been the successor
to SNOBOL4) was ever released.
If you know Snobol, don't expect the conversion to be immediate.
You can write a 3-line Arb() procedure, if you like. But it's not
built in. Icon offers low-level tools with which to construct your
own matching functions. It is very flexible, but what I'm trying to
say is that, at first, Snobol programmers often feel a bit lost.
Perhaps some former Snobol-ers can comment on this statement.
Icon is nice in the sense that it runs on almost all small and mid-range
machines, and on many high-end ones. It's very portable, and is pretty
much free.
-Richard
From icon-group-request@arizona.edu Wed Dec 5 23:33:53 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA10370; Wed, 5 Dec 90 23:33:53 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Wed, 5 Dec
1990 23:33 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA11733; Wed, 5 Dec 90 22:18:49
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Wed, 5 Dec 1990 23:33 MST
Date: 6 Dec 90 02:03:04 GMT
From: att!linac!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!van-bc!ubc-cs!alberta!herald.usask.ca!skorpio!gulati@ucbvax.Berkeley.EDU
(Neeraj Gulati)
Subject: Just a test ...
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <120BE8FBBC4010BB@Arizona.edu>
Message-Id: <1990Dec6.020304.18013@herald.usask.ca>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Saskatchewan
Please ignore !!
From icon-group-request@arizona.edu Thu Dec 6 07:34:40 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26318; Thu, 6 Dec 90 07:34:40 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 07:34 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19462; Thu, 6 Dec 90 06:21:58
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Dec 1990 07:34 MST
Date: 6 Dec 90 12:33:55 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: Klondike card game, version 1.41. part 1/4
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <553247FFCC4022BE@Arizona.edu>
Message-Id: <1687@hslrswi.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
This is a new version of the solitaire card game that I posted some
months ago. This one improved ICONisms, an improved user interface,
and a much better chance of actually running on any ANSI terminal.
There is even a man page, klondike.man, included in this message.
The source is now split into three files:
klondike.icn main program, top-level user-interface routines
kloncon.icn console I/O subroutines
klonsub.icn assorted other subroutines
To execute from scratch, I believe the following suffices:
icont -c kloncon klonsub
icont klondike
iconx klondike <<any options here>>
Should you wish to peruse the source, use a tab interval of 4, not 8.
NHA
---
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400: naz@hslrswi.hasler
UUCP: ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
--------------- cut here -------------------- cut here ---------------------
NAME
klondike -- one of the many versions of solitaire
SYNOPSIS
klondike -[ACD] [-B gameCount] [-R randomSeed]
DESCRIPTION
This is actually a popular variation on the Klondike version of
Solitaire (or Patience) as described on page 181 of my 1963
version of "Hoyle's Rules of Games". The difference is that
here we go through the deck (stock) 3 cards at a time instead
of one-by-one, and we allow it any number of times.
It should run on any ANSI-compatible terminal, but it looks
best on a PC, preferably color.
OPTIONS
Options may be either upper or lower case. They may be given
in any order. Parameters follow their options with whitespace
inbetween. Each option must be given as a separate argument.
-A disables automatically putting uncovered Ace cards
on the appropriate pile. Note that, in any case, it is
not allowed to put an Ace onto a stack, as this could lead
to building stacks which are too big to display with 25 lines.
-B count
Batch mode. The requested number of games is played and
the average number of cards promoted to the ace piles is
written to the standard output. No other I/O is performed.
-C disable the "click" for silent games
-D enable special debugging commands which, among other things,
allow one to cheat
-R seed
set the random seed to the designated value
COMMANDS
H or ? display a Help screen
^L (control-L) redraws the screen
A Automatic mode. Plays the game until nothing useful
remains to be done, or until any key is struck.
B Boss key. The screen is blanked and the current position
is saved. When the game is started again in the usual
way, this saved game will be automatically restored and
the save file deleted.
C Continuous mode. The computer plays games automatically
until a key is struck. Two statistics are displayed:
the number of games already played, and the total number
of aces which have been promoted to the ace piles.
M Move a card from the deck or a stack to a stack or an
ace pile.
Q Quit this game, with the opportunity to play another.
S Suggest a possible move. Hitting this key multiple times
results in multiple suggestions being displayed. When
there is nothing interesting left to do, it will suggest
"Thumb".
T Thumb. Remove the top 3 cards from the face-down deck
and lay them face-up on the face-up deck.
U Undo. This can be used all the way back to the start
of the current game.
Z Debug. This is only enabled when the -D option has
been given on the command line. There is a sub-menu
of commands available, including a (very brief) Help
summary.
The Move command takes two parameters: source and destination.
Possible sources are: D for the Deck of face-up cards; and a
number from 1 to 7 inclusive, meaning the corresponding stack.
Possible destinations are the stacks (1-7) and A for the
appropriate ace pile. For instance, to move the visible card
from the face-up deck to stack 4, one types the three characters:
"MD4". Actually, the "M" character itself is optional, which
explains why the "debug" command isn't invoked with a "D".
BUGS
Slow.
Doesn't use termcap for maximum portability.
The program's play is simplistic, with no concept of strategy.
FILES
klondike.sav Position is checkpointed here when the Boss key is used.
klondike.sv? Position checkpointed here with the "S" debug command.
"?" can be any (upper-case) character legal in your
filesystem.
ACKNOWLEDGEMENT
The inspiration, name, and user interface were lifted
wholesale from a game copyrighted in 1985 by Allyn Wade.
VERSION
1.41 -- 26 November, 1990
AUTHOR
Norman H. Azadian
naz@hslrswi
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400: naz@hslrswi.hasler
UUCP: ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Thu Dec 6 07:35:40 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26388; Thu, 6 Dec 90 07:35:40 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 07:34 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19656; Thu, 6 Dec 90 06:32:50
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Dec 1990 07:34 MST
Date: 6 Dec 90 12:43:12 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: klondike, version 1.41. part 3/4
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <55429BAFCC401D40@Arizona.edu>
Message-Id: <1689@hslrswi.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#kloncon.icn 901029 NHA
# Console interface routines for Klondike
# Requires ANSI.SYS (or NANSI.SYS) screen driver and a 25-line display.
#
# TO FIX:
#
#
# TO DO:
#
# - termcap for portability ??
# - click for each card moved in a stack ?
#
# constants
global suitID #suit identification chars
global isDOS # 1 when running under DOS
global monochrome # 1 when running Black&White
# Video control strings (ANSI.SYS)
global ESC
global Vnormal, Vreverse, Vblink, Vbold, VclearAll, VclearEOL, Vbell
global color #list of suit color strings
# i n i t C o n s t a n t s
# Initialize the program "constants". These are actually variables that
# are set just once at the beginning of the world.
procedure initConstants ()
local i
local Vred, Vblack #suit color strings
if \invisible then return
#ensure that we are dealing with an ANSI-compatible screen
writes ("\33[6n") #request cursor position report
#NOTE that the first character to match should be an ESCape.
#Unfortunately, reads() seems to eat that character
match ("[", reads (&input, 8)) |
stop ("Klondike: requires ANSI.SYS screen driver")
isDOS := find("MS-DOS", &host)
if \isDOS then {
i := ord (Peek([16r40, 16r49])) #BIOS display mode byte
case i of {
2 : monochrome := 1
3 : monochrome := &null #living color
7 : monochrome := 1
default : stop ("Klondike: unknown display mode ", i)
}
} else
monochrome := 1
ESC := "\33" #escape character
VclearAll := "\33[2J" #also homes cursor
VclearEOL := "\33[K"
Vnormal := "\33[0m"
Vbold := "\33[1m"
Vblink := "\33[5m"
Vreverse := "\33[7m"
Vbell := "\^G"
if \monochrome then {
Vred := Vnormal
Vblack := Vreverse
} else {
Vred := "\33[0;47;31m" # "extra" 0 seems to be necessary
Vblack := "\33[0;47;30m"
}
# Suits are: 1=Hearts, 2=Diamonds, 3=Clubs, 4=Spades
suitID := if \isDOS then "\3\4\5\6" else "HDCS"
color := [Vred, Vred, Vblack, Vblack]
end #initConstants
# i n i t S c r e e n
# Initialize output and write the fixed parts of the screen.
# initConstants() must have been called earlier.
procedure initScreen ()
local i
static vertical
initial {
vertical := if \isDOS then "\272" else "|"
}
if \invisible then return
if \monochrome then writes ("\33[=2h") #25x80 B&W text mode
else writes ("\33[=3h") #25x80 color text mode
writes (VclearAll, "\33[=7l") #clear screen, prevent wrap
every i := 1 to 7 do
writeStackNumber (i, Vnormal)
every i := 2 to 25 do
writes ("\33[",i,";64H", vertical)
if \isDOS then
writes ("\33[2;64H\311\315\315\315\315SOLITAIRE\315\315\315\315")
else
writes ("\33[2;64H=====SOLITAIRE====")
end #initScreen
# w r i t e S t a c k N u m b e r
# Write the indicated stack number with the specified video attribute.
# Cursor position is preserved -- WARNING: THIS IS NOT NESTABLE.
procedure writeStackNumber (num, attr)
if \invisible then return
writes (ESC, "[s") #save cursor position
writeCursor (1, [2,11,20,29,38,47,56][num])
writes (attr, num, Vnormal)
writes (ESC, "[u") #restore cursor position
end #writeStackNumber
# w r i t e C u r s o r
# Position the cursor to row,col.
# Screen origin (top left corner) is row=1 and col=1.
procedure writeCursor (row, col)
if /invisible then
writes ("\33[", row, ";", col, "H")
end #writeCursor
# w r i t e F r o n t
# Displays an image of the specified card fronts at the specified spot.
# WARNING: this eats the list that you provide -- pass a copy() if you care!!
# Top left corner of the first card will be placed at the specified position.
# Successive cards are displayed two rows higher (lower position on the screen).
# Cursor need not be in any particular position before this, and is left
# in a random position afterwards. Video is always left normal (not reversed).
# Cards are 7 columns wide by 5 rows tall.
# With 25 rows, we can put 12 cards in a stack (assuming we start in row 2).
# But if there are 11 in the stack we can only display 4 rows of the top card.
# If there are 12 cards, we can only display 2 rows of the topmost card.
##We can only write a row at a time due to a problem with ANSI col 80 handling.
procedure writeFront (cardlist, row, col)
local suit, rank, card
static vertical, topHorizontal, bottomHorizontal
initial {
if \isDOS then {
vertical := "\263"
topHorizontal := "\332\304\304\304\304\304\277"
bottomHorizontal := "\300\304\304\304\304\304\331"
} else {
vertical := "|"
topHorizontal := "-------"
bottomHorizontal := "-------"
}
}
while card := get(cardlist) do {
#first 2 rows of card
writeCursor (row+0, col);
writes (Vreverse, topHorizontal)
writeCursor (row+1, col);
writes (vertical, color[card.suit], "A23456789TJQK"[card.rank],
suitID[card.suit], Vreverse, " ", vertical)
if (*cardlist = 0) & (row < 24) then {
#next 2 rows of top card unless it's the 12th card on the stack
writeCursor (row+2, col);
writes (Vreverse, vertical, " ", vertical)
writeCursor (row+3, col);
writes (vertical, " ",color[card.suit],"A23456789TJQK"[card.rank],
suitID[card.suit], Vreverse, vertical)
if row < 22 then {
#last row of card unless it's the 11th on the stack
writeCursor (row+4, col);
writes (bottomHorizontal)
}
}
row +:= 2
}
writes (Vnormal)
end #writeFront
# w r i t e B a c k
# Puts an image of the back of a card at the specified spot on the screen.
procedure writeBack (row, col)
static backLine
initial {
backLine := repl (if \isDOS then "\260" else "#", 7)
}
if \invisible then return
writeCursor (row+0, col); writes (backLine)
writeCursor (row+1, col); writes (backLine)
writeCursor (row+2, col); writes (backLine)
writeCursor (row+3, col); writes (backLine)
writeCursor (row+4, col); writes (backLine)
end #writeBack
# w r i t e B l a n k
# Blanks a card-sized area at the specified spot on the screen.
procedure writeBlank (row, col)
static blankLine
initial {
blankLine := repl (" ", 7)
}
if \invisible then return
writeCursor (row+0, col); writes (blankLine)
writeCursor (row+1, col); writes (blankLine)
writeCursor (row+2, col); writes (blankLine)
writeCursor (row+3, col); writes (blankLine)
writeCursor (row+4, col); writes (blankLine)
end #writeBlank
# w r i t e S t a c k
# Display the specified stack. Left end is bottom of stackUp, top of stackDown.
# Stacks start in row 2, column1; with 2 columns between stacks.
# last[] holds, for each stack, the total number of visible cards
# on that stack as of the last time writeStack() was called. This allows
# us to simply draw (or erase) the cards that have been added (or subtracted).
# By special arrangement, this routine can be called with a negative stack
# number! This is a hint that our idea of what is on the display is actually
# wrong, and therefore the entire stack needs to be re-displayed. This can
# happen in two situations: 1) in refreshScreen(), the entire screen is cleared
# before calling writeStack(); 2) in undo() when undoing a move between
# stacks, the bottom card needs to be changed, although the normal algorithm
# would consider that it is already correctly displayed. Note that in neither
# case is the stack shrinking, therefore we don't need to worry about erasing
# any cards that were displayed last time.
procedure writeStack (n)
local row, col, s
static last, blankLine, firstRow, lastRow
initial {
last := [0,0,0,0,0,0,0]
blankLine := repl (" ", 7)
firstRow := [2,4,6,8,10,12,14,16,18,20,22,24] #first row of a card
lastRow := [6,8,10,12,14,16,18,20,22,24,25,25] #last row of a card
}
if \invisible then return
if n < 0 then {
n := -n
last[n] := 0 #force complete re-write
}
col := 1 + ((n -1) * 9) #leftmost column for this stack
if *stackUp[n] <= last[n] then {
#the stack just got smaller (or stayed the same)
#blank out two rows for each card that has been removed
row := lastRow[last[n]] #last row used by top card
while *stackUp[n] < last[n] do {
writeCursor (row-0, col); writes (blankLine)
writeCursor (row-1, col); writes (blankLine)
row -:= 2
last[n] -:= 1 #count and update simultaneously
}
dieIf (*stackUp[n] ~= last[n], last[n])
#re-write new top card
if *stackUp[n] = 0 then
if *stackDown[n] = 0 then
writeBlank (2, col)
else
writeBack (2, col)
else
writeFront ([stackUp[n][-1]], firstRow[last[n]], col)
} else {
#the stack just got bigger -- display new cards
s := stackUp[n][last[n]-(*stackUp[n]):0] #list of new cards
writeFront (s, firstRow[last[n]+1], col)
last[n] := *stackUp[n] #remember how much is displayed
}
writeCursor (2, (7 + col))
writes (" 123456???"[1+*stackDown[n]]) #display the number of hidden cards
end #writeStack
# w r i t e P i l e
# Displays an image of the specified ace pile, face up (or blank if empty)
procedure writePile (n)
static pileRow, pileCol
initial {
pileRow := [3,3,9,9]
pileCol := [66,74,66,74]
}
if \invisible then return
if 0 = pile[n] then writeBlank (pileRow[n], pileCol[n])
else writeFront ([card(n,pile[n])], pileRow[n], pileCol[n])
end #writePile
# w r i t e D e c k D o w n
# Displays an image of deckDown (the face-down deck) in the proper spot.
procedure writeDeckDown ()
if \invisible then return
if 0 < *deckDown then
writeBack (21, 74)
else
writeBlank (21, 74)
writeCursor (20, 76)
writes (right(*deckDown, 2))
end #writeDeckDown
# w r i t e D e c k U p
# Displays an image of deckUp (the face-up deck) in the proper spot.
procedure writeDeckUp ()
if \invisible then return
if 0 < *deckUp then
writeFront ([deckUp[1]], 21, 66)
else
writeBlank (21, 66)
writeCursor (20, 68)
writes (right(*deckUp, 2))
end #writeDeckUp
# w r i t e I n f o
# Displays a new short string (up to 12 printing characters) in the
# officially approved information area of the screen.
# An empty string results in clearing the area and restoring normal attributes.
procedure writeInfo (s)
if \invisible then return
writeCursor (16, 65)
writes (Vnormal, VclearEOL)
if *s ~= 0 then writes (s)
end #writeInfo
# c l i c k
# Make a quick sound to accompany card transfers
procedure click ()
local x
if (\clicking) & (\isDOS) then {
x := InPort (16r61)
OutPort (16r61, 3)
OutPort (16r61, x)
}
end #click
# g e t C m d C h a r
# Returns an upper-case command character, echoed to current cursor position.
# Fails if character wasn't "normal" and complaint was made.
# For ESC, abort information is written, and ESC is returned.
# Normal calling sequence (from within a command procedure) is thus:
# until (s := getCmdChar ())
# if s == ESC then fail
procedure getCmdChar ()
local s
s := getch () #get command character
if s == "\0" then { #non-ASCII character
getch () #discard keyboard scan code
complain ()
fail
}
s := map (s, &lcase, &ucase)
if s == ESC then
writeInfo (Vbold || "Cmd Aborted.")
else
writes (s) #echo the command character
return s
end #getCmdChar
# c o m p l a i n
# Let the boob know he done something wrong
# The short beep produced under isDOS is not as annoying as the normal beeeeep.
procedure complain ()
local x
writeInfo (Vbold || "INVALID")
if \clicking then
if \isDOS then {
x := InPort (16r61)
every 1 to 22 do
OutPort (16r61, 3)
OutPort (16r61, x)
} else
writes (Vbell)
end #complain
# r e f r e s h S c r e e n
# Re-write entire screen.
procedure refreshScreen ()
if \invisible then return
initScreen ()
every writeStack (-1 to -7 by -1)
every writePile (1 to 4)
writeDeckDown ()
writeDeckUp ()
end #refreshScreen
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400: naz@hslrswi.hasler
UUCP: ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Thu Dec 6 07:35:46 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26395; Thu, 6 Dec 90 07:35:46 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 07:34 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19678; Thu, 6 Dec 90 06:33:14
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Dec 1990 07:35 MST
Date: 6 Dec 90 12:44:22 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: klondike, version 1.41. part 4/4
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <555A54FD6C4022C1@Arizona.edu>
Message-Id: <1690@hslrswi.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#klonsub.icn 901029 NHA
#subroutines for Klondike
# d i e I f
# If the first argument succeeds, then write out the remaining args & die.
# Note that the remaining arguments must succeed.
procedure dieIf (failed, writeArgs[])
every writes (&output, !writeArgs)
write (&output)
display ()
every writes (&errout, !writeArgs)
write (&errout)
runerr (500)
end #dieIf
# f i t O n S t a c k
# Given a card and a stack number, fail unless card can be added to the stack.
# Note that we disallow putting an Ace on a stack, period. This prevents
# ever building a stack with 13 cards, which we can't display in 25 rows.
procedure fitOnStack (c, n)
local top #top card on stack
if *stackUp[n] = 0 then {
dieIf (*stackDown[n] ~= 0, "Up empty, Down not")
if c.rank ~= 13 then fail #only a king can go to empty stack
} else {
top := stackUp[n][-1] #copy of top card
if (c.rank ~= (top.rank - 1)) then fail #wrong rank
if (c.suit < 3) & (top.suit < 3) then fail #same color
if (c.suit > 2) & (top.suit > 2) then fail #same color
if c.rank = 1 then fail #no ace on stack
dieIf (*stackUp[n] >= 12, "stack too big")
}
return #success
end #fitOnStack
# c h e c k 4 a c e
# Only has an effect when global automaticAce is set!
# Given a stack number, check for an ace as the top of stackUp[n].
# If present, move it over to it's ace pile, turn over the next card
# from stackDown, and check again.
# Must not be more than one up card in stack.
# Returns a string of the operations performed.
procedure check4ace (n)
local c, op
op := ""
if \automaticAce then {
dieIf (1 < *stackUp[n])
while 0 < *stackUp[n] do {
c := stackUp[n][1] #copy of (top = bottom) up card
if c.rank = 1 then { #it's an ace!
pop (stackUp[n]) #remove it from the stack
pile[c.suit] := 1 #move to ace pile
op ||:= c.suit
push (stackUp[n], get(stackDown[n])) #turn over card underneath
writeStack (n)
writePile (c.suit)
click ()
} else
break #not an ace
}
}
return op
end #check4ace
# m o v e S t a c k
# Move a stack to another stack, no questions asked.
# Updates video and audio.
# Returns any automatic ace operations that were done as a consequence.
##It would be nice to do this in a visually and audibly more satisfying way
procedure moveStack (src, dst)
while put (stackUp[dst], get(stackUp[src]))
put (stackUp[src], get(stackDown[src]))
writeStack (src)
writeStack (dst)
click ()
return check4ace (src)
end #moveStack
# m o v e
# This is the internal move, taking a operation string. No Thumbs allowed.
# Upon success it returns the (possibly modified) operation string.
procedure move (op)
local src, dst, c, moved
dieIf (op[1] ~== "M", "op is ", op)
src := op[2]
dst := op[3]
moved := 0
if src == "D" then {
c := deckUp[1]
if dst == "A" then { # Deck -> Ace
if c.rank = (pile[c.suit] + 1) then {
op[4] := c.suit # Deck -> Ace: fits - do it
pile[c.suit] +:= 1
writePile (c.suit)
moved := 1
} else
fail # Deck -> Ace: doesn't fit
} else { # Deck -> stack
if fitOnStack (c, dst) then {
put (stackUp[dst], c) # Deck -> stack: fits - do it
writeStack (dst)
moved := 1
} else
fail # Deck -> stack: doesn't fit
}
while moved ~= 0 do {
pop (deckUp)
writeDeckUp () # Deck -> somewhere, with success
click ()
moved := 0
if \automaticAce then {
if (c := deckUp[1]).rank = 1 then { #automatic Ace handling
pile[c.suit] := 1
op ||:= c.suit
writePile (c.suit)
moved := 1
}
}
}
} else {
if dst == "A" then { # stack -> Ace
c := stackUp[src][-1] #copy of card on top of stack
if c.rank = (pile[c.suit] + 1) then {
op[4] := c.suit # stack -> Ace: fits - do it
pile[c.suit] +:= 1
pull (stackUp[src])
writeStack (src)
click ()
writePile (c.suit)
if *stackUp[src] = 0 then {
op[4] +:= 4 #mark this case for undo()
put (stackUp[src], get(stackDown[src])) #turn over a card
writeStack (src)
click ()
op ||:= check4ace (src)
}
} else {
fail # stack -> Ace: doesn't fit
}
} else { # stack -> stack
if fitOnStack (stackUp[src][1], dst) then {
# stack -> stack: fits - do it
op[4] := "123456789abcdef"[*stackUp[src]]
op ||:= moveStack (src, dst)
} else
fail # stack -> stack: doesn't fit
}
}
return op #success
end #move
# t h u m b
# Move to next spot in deckDown
# Returns the operation performed (usually just "T3"), or fail if none possible.
procedure thumb ()
local c, op, moved
if *deckDown = *deckUp = 0 then
return complain() #no cards left in the deck
if *deckDown = 0 then
while push (deckDown, pop(deckUp))
op := "T" || if *deckDown < 3 then *deckDown else 3
push (deckUp, pop(deckDown))
push (deckUp, pop(deckDown))
push (deckUp, pop(deckDown))
writeDeckDown ()
moved := 1
while moved ~= 0 do {
writeDeckUp ()
click ()
moved := 0
if \automaticAce then {
if deckUp[1].rank = 1 then {
c := pop (deckUp)
pile[c.suit] := 1
op ||:= c.suit
writePile (c.suit)
moved := 1
}
}
}
return op
end #thumb
# u n d o
# backup one move, including any automatic ace moves
procedure undo ()
local op, suit
writes ("ndo")
if op := pop (ops) then {
writeInfo (op)
# op looks like: Msdixxx
# where x is an [optional] number 1..4 of an ace pile
# and s is either a stack number or "D"
# and d is either "A" or a number 1..7 of a stack
# and i is an extra piece of info which may be valid
case op[1] of {
"M" : {
dieIf ((*op < 4) | ((/automaticAce) & (4 < *op)), op)
if op[2] == "D" then {
#Move cards from Ace piles to deck, starting at end
while 4 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
push (deckUp, card(suit,1))
writeDeckUp ()
click ()
op[-1] := ""
}
if op[3] == "A" then {
# unMove Deck to Ace op[4]
suit := op[4]
push (deckUp, card(suit,pile[suit]))
pile[suit] -:= 1
writePile (suit)
} else {
# unMove Deck to stack op[3]
push (deckUp, pull(stackUp[op[3]]))
writeStack (op[3])
}
writeDeckUp ()
} else {
#Move cards from Ace piles to stack, starting at end
while 4 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
dieIf (1 < *stackUp[op[2]])
push (stackDown[op[2]], pull(stackUp[op[2]]))
push (stackUp[op[2]], card(suit,1))
writeStack (op[2])
click ()
op[-1] := ""
}
if op[3] == "A" then {
# unMove stack op[2] to Ace pile op[4]
suit := op[4]
if 4 < suit then {
suit -:= 4 #ace pile card was last on stack
dieIf (1 < *stackUp[op[2]])
push (stackDown[op[2]], pull(stackUp[op[2]]))
}
put (stackUp[op[2]], card(suit,pile[suit]))
pile[suit] -:= 1
writePile (suit)
writeStack (op[2])
} else {
# unMove top op[4] cards on stack op[2]
# to stack op[3]
dieIf (1 < *stackUp[op[2]])
push (stackDown[op[2]], pull(stackUp[op[2]]))
every 1 to ("16r" || op[4]) do
push (stackUp[op[2]], pull(stackUp[op[3]]))
writeStack (op[3])
writeStack (-op[2])
}
}
}
"T" : {
dieIf ((/automaticAce) & (*op ~= 2))
### op looks like: Tcxx
### where c is the number of cards thumbed (usually 3)
### and x is an optional number 1..4 of an ace pile
### There can be 0,1,2, or 3 of these x's.
# move cards from Ace piles to deck, starting at end
while 2 < *op do {
suit := op[-1]
pile[suit] := 0
writePile (suit)
push (deckUp, card(suit,1))
writeDeckUp ()
click ()
op[-1] := ""
}
# then undo the Thumb operation itself
dieIf (*deckUp = 0)
every 1 to op[2] do
push (deckDown, pop(deckUp))
if *deckUp = 0 then
while push (deckUp, pop(deckDown))
writeDeckUp ()
writeDeckDown ()
}
default : stop ("Klondike: unknown operation `", op, "' in ops[]")
}
click ()
} else {
## Admittedly this is a bit of a kluge, but better than nothing ?
if *deckDown = 0 then
while push (deckDown, pop(deckUp))
writeDeckUp ()
writeDeckDown ()
writeInfo ("Stack Empty")
}
end #undo
# s h o w L i s t
# Display a list of cards at the current cursor position.
# Intended for debugging only .
procedure showList (lst)
local c
every c := !lst do
writes (color[c.suit], "A23456789TJQK"[c.rank], suitID[c.suit],
Vnormal, " ");
end #showList
# c a r d 2 s t r
# Given a list of card records, returns a string representation.
# Even an empty list results in a non-zero string length.
procedure card2str (lst)
local c, s
s := "$"
every c := !lst do
s ||:= string(c.suit) || "123456789abcd"[c.rank]
return s
end #card2str
# s t r 2 c a r d
# Given a string [as generated by card2str()],
# return corresponding list of card records.
# Fails if the string is invalid.
procedure str2card (s)
local cc, i
if s[i:=1] ~== "$" then fail
cc := []
while put (cc, card(s[i+:=1], integer("14r"||s[i+:=1])))
return cc
end #str2card
# s a v e S t a t e
# Saves the current state in the named file, which is created/overwritten
# as necessary.
# Fails if the state was not successfully saved.
procedure saveState (filename)
local f, i
(f := open (filename, "c")) | fail
write (f, &dateline)
write (f, if \automaticAce then 1 else 0)
write (f, if \clicking then 1 else 0)
write (f, firstSeed)
write (f, lastSeed)
write (f, &random)
every write (f, !pile)
every write (f, card2str(!stackUp))
every write (f, card2str(!stackDown))
write (f, card2str(deckUp))
write (f, card2str(deckDown))
write (f, totalGames)
write (f, totalAces)
every write (f, !ops)
return close (f)
end #saveState
# r e s t o r e S t a t e
# Restore game from the named file.
# Fails if the file isn't there, isn't readable, or isn't correct format.
# Otherwise returns date the file was last written.
# Note that we do not update the screen here !!
procedure restoreState (filename)
local f, date
if not (f := open (filename, "r")) then fail
if (not (date := read(f))) | (*date = 0) then fail
automaticAce := if read (f) == "0" then &null else 1
clicking := if read (f) == "0" then &null else 1
firstSeed := read (f)
lastSeed := read (f)
&random := read (f)
every ((!pile) := read(f))
every ((!stackUp) := str2card (read(f)))
every ((!stackDown) := str2card (read(f)))
deckUp := str2card (read(f))
deckDown := str2card (read(f))
totalGames := read (f)
totalAces := read (f)
ops := []
while push (ops, read (f))
dieIf (not close (f), "can't close")
return date
end #restoreState
# n e w G a m e
# Set up all the global variables for a new game.
# Returns the seed used to generate this game.
procedure newGame ()
local i, j, s, seed
initScreen ()
#initialize deck, stacks, piles
ops := [] #no operations done yet
deckUp := [] #deck in hand, face-up
deckDown := [] #deck in hand, face-down
stackUp := list(7, 0) #columns on table, face up
stackDown := list(7, 0) #columns on table, face down
pile := list(4, 0) #aces - only top rank stored
every i := 1 to 4 do
every j := 1 to 13 do
put (deckDown, card(i, j)) #take cards out of the box
seed := &random
if not \invisible then #Vblink not defined in Batch mode
writeInfo (Vblink || "Shuffling")
every 1 to 100 do
?deckDown :=: ?deckDown
writeInfo ("")
every !stackUp := []
every !stackDown := []
every i := 1 to 7 do {
push (stackUp[i], get(deckDown))
writeStack (-i)
click ()
every j := (i+1) to 7 do {
push (stackDown[j], get(deckDown))
writeStack (-j)
click ()
}
### writeStack (-i) ### this replaces 2 calls above
}
writeDeckDown()
#handle any Aces which are showing
every i := 1 to 7 do
if *(s := check4ace (i)) ~= 0 then
push (ops, "M" || string(i) || "A" || string(integer(s) + 4))
return seed
end #newGame
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400: naz@hslrswi.hasler
UUCP: ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From icon-group-request@arizona.edu Thu Dec 6 07:36:54 1990
Resent-From: icon-group-request@arizona.edu
Received: from HOPEY.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA26473; Thu, 6 Dec 90 07:36:54 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 07:35 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA19641; Thu, 6 Dec 90 06:32:04
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Dec 1990 07:36 MST
Date: 6 Dec 90 12:42:14 GMT
From: eru!hagbard!sunic!mcsun!cernvax!chx400!hslrswi!naz@bloom-beacon.mit.edu
(Norman H. Azadian)
Subject: klondike, version 1.41. part 2/4
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <5580B0A18C401FC4@Arizona.edu>
Message-Id: <1688@hslrswi.UUCP>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: Hasler AG
#klondike.icn 900720 NHA
#The Klondike version of Solitaire.
# Requires ANSI.SYS (or NANSI.SYS) screen driver and a 25-line display.
#
# TO FIX:
#
#
#
# TO DO:
#
# - Use space to step to next non-thumb move, and enter to do it ???
# - Implement an heuristic to discover optimal play strategy.
#
link kloncon #console I/O
link klonsub #general subroutines
record card(suit, rank) #suit is 1..4, rank is 1..13
# variables
global deckUp, deckDown, stackUp, stackDown #collections of card
global pile #ace piles - top rank only
global ops #list of all operations done
global debugging, automaticAce #command-line flags
global invisible, clicking #visual, audible feedback
global firstSeed, lastSeed #&random remembered
global totalGames, totalAces #ace pile statistics
# a u t o m a t i c 1
# Do 1 move, thumbing as necessary to achieve it.
# Fails if there is nothing useful left to do.
# This is an internal routine that doesn't worry at all about the user.
procedure automatic1 ()
local s, thumbCount
thumbCount := 0
while thumbCount <= ((*deckUp + *deckDown + 2) / 3) do {
if s := suggest() then {
push (ops, move ("M" || s || "0"))
thumbCount := 0
return;
} else { #no good move found -- thumb
if (*deckUp = 0) & (*deckDown = 0) then
fail #no cards left to thumb through
push (ops, s := thumb())
if 2 < *s then
return #must have turned up an Ace
thumbCount +:= 1
}
}
end #automatic1
# a u t o m a t i c
# Run the game, as far as possible, untouched by human hands
# This is an internal routine that only worries a little about the user.
# Returns when either there is nothing useful left to do or a key is struck.
procedure automatic ()
local s, thumbCount
thumbCount := 0
repeat {
if kbhit () then
return #stopped by human intervention
if pile[1] = pile[2] = pile[3] = pile[4] = 13 then
return #victory
automatic1 () | return
}
end #automatic
# u a u t o m a t i c
# Play this hand automatically, untouched by human hands.
# This is the fuction that interacts with the user.
procedure uautomatic ()
writes ("utomatic")
automatic()
if kbhit() then
if getch() == "\0" then getch()
end #uautomatic
# u c o n t i n u o u s
# Plays automatic games -- forever (or until any keystroke)
procedure ucontinuous()
writes ("ontinuous")
repeat {
writeInfo (string(totalGames) || " " || string(totalAces))
automatic()
if kbhit() then {
if getch() == "\0" then #eat stopping char(s)
getch()
return
} else
totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
totalGames +:= 1
lastSeed := newGame()
}
end #ucontinuous
# u h e l p
# Provide command summary for user, plus statistics to date, if any.
procedure uhelp ()
write (VclearAll, Vnormal)
write ("Klondike version 1.41 901126 NHA\t\t", &version)
write ("\n\nThe following commands are available:\n")
write ("\t", Vbold, "^L\tre-draw", Vnormal, " screen")
write ("\t", Vbold, "A\tAutomatic", Vnormal, " mode -- plays 1 game by itself until any key is hit")
write ("\t", Vbold, "B\tBoss", Vnormal, " key for when you-know-who visits")
write ("\t", Vbold, "C\tContinuous", Vnormal, " mode -- plays games continuously until any key hit")
write ("\t", Vbold, "H,?\tHelp", Vnormal, ", this help screen")
write ("\t", Vbold, "M\tMove", Vnormal, " card (or stack) from Deck/Stack to Stack/Ace pile")
write ("\t", Vbold, "Q\tQuit", Vnormal, " this game")
write ("\t", Vbold, "S\tSuggest", Vnormal, " (another) possible move")
write ("\t", Vbold, "T\tThumb", Vnormal, " through the deck")
write ("\t", Vbold, "U\tUndo", Vnormal, " -- back up one move")
if \debugging then
write ("\t", Vbold, "Z\tDebug", Vnormal)
write ("\t", Vbold, "ESC\tEscape", Vnormal, " -- abort current command")
if totalGames ~= 0 then
write ("\n\ntotalGames = ", totalGames, " totalAces = ", totalAces,
" average = ", real(totalAces) / real(totalGames))
write ("\n\n", Vblink, "Press any key to resume game", Vnormal)
if getch() == "\0" then getch()
refreshScreen ()
end #uhelp
# u m o v e
# Move a card from deck to stack, or from stack to ace pile,
# or move a stack to another stack.
# Parameter is the source [1-7 or D] or &null to indicate that "M" was used
# and therefore source should be gathered from the keyboard.
# Fails if indicated move is not possible
# This is the routine that interacts with the user.
procedure umove (src)
local dst, c, op, moved
if \src then
writes ("\bMove ", Vbold, src)
else {
writes ("ove " || Vbold);
until (src := getCmdChar ())
if src == ESC then return
}
if src == "D" then {
if *deckUp = 0 then fail
} else {
if not any ('1234567', src) then fail
if *stackUp[src] = 0 then fail
writeStackNumber (src, Vblink)
}
writes (Vnormal || " to " || Vbold)
until (dst := getCmdChar ())
if src ~== "D" then writeStackNumber (src, Vnormal)
if dst == ESC then return
if not any ('A1234567', dst) then fail
if dst == src then fail
return push (ops, move("M" || src || dst || "0"))
end #umove
# s u g g e s t
# Find a (reasonable) possible move in this situation
# This is the internal routine.
procedure suggest ()
local i, j, k, c
#look at deckUp to see if the top card fits on a pile
if c := deckUp[1] then
if c.rank = (pile[c.suit] + 1) then
suspend "DA"
#look at deckUp to see if the top card fits on a stack
if c := deckUp[1] then
every i := 1 to 7 do
if fitOnStack (c, i) then
suspend "D" || string(i)
#look at each stack to see if top card can be put on ace pile
every i := 1 to 7 do
if c := stackUp[i][-1] then #top card
if c.rank = (pile[c.suit] + 1) then
suspend string(i) || "A"
#look at each stack to see if something can be (reasonably) moved
every i := 7 to 1 by -1 do
every j := 1 to 7 do
if fitOnStack (stackUp[i][1], j) then {
if (0 < *stackDown[i]) then
suspend string(i) || string(j)
else {
# possibility, but since there are no cards hidden under
# this pile, we reject it UNLESS there are no empty slots
# AND one of the following is true:
# 1) deckUp[1].rank = 13
# 2) there is a king with cards hidden beneath it
c := 0 #number of empty stacks
every k := 1 to 7 do
if *stackUp[k] = 0 then c +:= 1
if c = 0 then
if (deckUp[1].rank = 13) |
(every k := 1 to 7 do
if (stackUp[k][1].rank = 13) &
(0 < *stackDown[k]) then
break #success
)
then
suspend string(i) || string(j)
}
}
#punt
fail
end #suggest
# u s u g g e s t
# Suggest a (reasonable) possible move in this situation.
# Repeated invocations produce successive possibilities, until the
# only thing left to do is Thumb. After this, it cycles around to the start.
procedure usuggest (another)
static suggestions, i
local s, ss
writes ("uggest")
if another = 0 then {
suggestions := [] #generate a new list of suggestions
every put (suggestions, suggest())
i := 0
}
if ss := suggestions[i+:=1] then {
s := "Move " || if ss[1] == "A" then "Ace"
else if ss[1] == "D" then "Deck"
else ss[1]
s ||:= " to " || if ss[2] == "A" then "Ace" else ss[2]
writeInfo (s)
} else {
writeInfo ("Thumb")
i := 0
}
end #usuggest
# u t e r m i n a t e
# Parameter should be non-zero if termination is due to complete success.
# Returns success to quit this game and start another.
# Returns failure to just continue this game.
# If program termination is wished, that is done right here.
procedure uterminate (victory)
local s
if \victory then {
totalAces +:= 52
pile[1] := pile[2] := pile[3] := pile[4] := 0 #prevent victory loops
writeCursor (12, 22)
writes (Vbold, Vblink, "Congratulations -- You've WON !!!", Vnormal)
} else
writes ("uit")
writeInfo (Vbold || "Another game? ")
until (s := getCmdChar ())
if s == ESC then fail() #didn't really want to quit anyway
if s == "Y" then return #please start a new game
if s ~== "N" then return complain ()
#program termination requested
writes ("\33[=7h", Vnormal) #set cursor wrap mode, normal attr
totalGames +:= 1
if /victory then
totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
write (VclearAll, "In ", totalGames, " games, you put ", totalAces,
" cards on the ace piles")
write ("average = ", real(totalAces) / real(totalGames), " per game")
exit ()
end #uterminate
# u d e b u g
# Additional commands to support the implementer.
procedure udebug ()
local s, d, c, name
if not \debugging then return complain()
writes ("\bDebug ")
until (s := getCmdChar ())
case s of {
ESC : fail
"A" : {
writes ("gain")
&random := lastSeed
writeCursor (23, 1)
write (Vbold, "&random set. Quit to play this game again.",
Vnormal, VclearEOL)
}
"D" : display()
"H"|"?" : {
writes (if s == "?" then "\bhelp" else "elp")
writeCursor (23, 1)
write (Vbold,
"Again, Dump, Options, Move, Peek{1-7UD}, Restore, Save, Toggle{ACT}.",
Vnormal, VclearEOL)
}
"M" : {
writes ("ove ")
until (s := getCmdChar ()) #Source
if s == ESC then fail
if s == "A" then fail
until (d := getCmdChar ()) #Destination
if d == ESC then fail
if d == s then fail
if not any('1234567', d) then fail
if s == "D" then {
if *deckUp = 0 then fail
put (stackUp[d], get(deckUp))
writeDeckUp ()
writeStack (d)
push (ops, "MD" || d || "0")
} else {
c := "123456789abcdef"[*stackUp[s]]
moveStack (s, d)
push (ops, "M" || s || d || c)
}
}
"O" : {
writes ("ptions")
writeCursor (23, 1)
write (Vbold,
if \automaticAce then "AutomaticAce " else " ",
if \clicking then "Clicking " else " ",
" &trace=", &trace,
" seeds=", firstSeed, ",", lastSeed, Vnormal, VclearEOL)
}
"P" : {
writes ("eek ")
until (s := getCmdChar ())
if s == ESC then fail
writeCursor (23, 1)
writes (VclearEOL, Vnormal)
if any('1234567', s) then showList (stackDown[s])
else if s == "D" then showList (deckDown)
else if s == "U" then showList (deckUp)
else complain ()
}
"R" : {
writes ("estore")
until (s := getCmdChar ())
if s == ESC then fail
name := "klondike.sv" || s
if (d := restoreState(name)) then {
refreshScreen()
writeCursor (23, 1)
write (Vbold, "Restored position from file ", name,
" of ", d, Vnormal, VclearEOL)
} else {
writeCursor (23, 1)
write (Vblink, "Can't restore from file ", name, ".",
Vnormal, VclearEOL)
}
}
"S" : {
writes ("ave ")
until (s := getCmdChar ())
if s == ESC then fail
name := "klondike.sv" || s
writeCursor (23, 1)
if saveState (name) then
write (Vbold, "Position saved in file ",name,
Vnormal, VclearEOL)
else
write (Vblink, "Can't save in file ", name, ".",
Vnormal, VclearEOL)
}
"T" : {
writes ("oggle ")
until (s := getCmdChar ())
if s == ESC then fail
case s of {
"A" : automaticAce := if \automaticAce then &null
else 1
"C" : clicking := if \clicking then &null else 1
"T" : &trace := if &trace = 0 then -1 else 0
default : complain ()
} #case for Toggle
}
default : complain ()
} #case for Debug command
end #udebug
# u b o s s
# Cheese it, the Fuzz.
# Quick -- clear the screen and save the state in a file.
procedure uboss ()
writes ("oss")
writes ("\33[=7h", VclearAll, "C>") #set cursor-wrap mode, look innocent
saveState ("klondike.sav")
exit ()
end #uboss
# m a i n
procedure main (av)
local s, prevsCmd, maxGames
# set defaults
automaticAce := 1 # automatic ace handling
clicking := 1 # give audible feedback
debugging := &null # no debugging allowed
invisible := &null # let's see the action
maxGames := &null # interactive mode
&random := map (&clock, ":", "0") # randomize the seed
# deal with command-line parameters
while s := get (av) do
case map (s, &lcase, &ucase) of {
"-A" : automaticAce := &null #disable automatic ace handling
"-B" : maxGames := get (av) #batch mode, this many games
"-C" : clicking := &null #run silent
"-D" : debugging := 1 #grant all sorts of perqs
"-R" : &random := get (av) #unrandomize
default : {write ("klondike [-ACD] [-B gameCount] [-R randomSeed]")
stop("klondike: bogus option ", s) }
}
totalGames := totalAces := 0
if \maxGames then {
# In Batch mode there is absolutely no console I/O.
# The requested number of games is played
# and the average result is printed on the standard output.
invisible := 1
clicking := &null
totalGames := maxGames
while 0 <= (maxGames -:= 1) do {
newGame ()
while automatic1 () #don't allow user to interrupt
totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
}
write (real(totalAces) / real(totalGames))
exit ()
}
initConstants() #for console I/O
firstSeed := &random #initial seed
lastSeed := newGame ()
#if last game terminated via the Boss key, then restore it now
if restoreState ("klondike.sav") then {
refreshScreen ()
writeInfo ("Game restored")
close (open ("klondike.sav", "c")) #truncate boss save file
}
repeat { #game loop
prevsCmd := "x" #anything but "S"uggest
#respond to user input
repeat { #command loop
writeCursor (18, 65)
writes (VclearEOL || Vnormal || "> ") #clear command line
if pile[1] = pile[2] = pile[3] = pile[4] = 13 then
if uterminate (1) then break # VICTORY!
s := getCmdChar ()
writeInfo ("") #clear info line
writeCursor (18, 68)
case s of {
"?"|"H" : uhelp()
"1"|"2"|"3"|"4"|"5"|"6"|"7"|"D" :
if not umove(s) then complain()
"A" : uautomatic() #look Ma, no hands!
"B" : uboss() #bail out -- quick
"C" : ucontinuous() #no hands, forever
"M" : if not umove(&null) then complain()
"Q" : if uterminate(&null) then break #new game
"S" : usuggest (if s == prevsCmd then 1 else 0)
"T" : { writes("humb"); push(ops, thumb()) }
"U" : undo()
"Z" : udebug()
"\^L" : refreshScreen()
ESC : s #do nothing here
default : complain()
} #case
prevsCmd := s
} #repeat command
totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
totalGames +:= 1
lastSeed := newGame ()
} #repeat game
end #main
--
PAPER: Norman Azadian; Ascom AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400: naz@hslrswi.hasler
UUCP: ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!naz
VOICE: +41 31 63 2178 BITNET: naz%hslrswi.UUCP@cernvax.BITNET
From goer%sophist@gargoyle.uchicago.edu Thu Dec 6 14:22:17 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from MERLIN.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA15356; Thu, 6 Dec 90 14:22:17 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 14:21 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA24137; Thu, 6 Dec 90 15:21:01 CST
Received: by sophist (4.1/UofC3.1X) id AA07162; Thu, 6 Dec 90 15:24:20 CST
Resent-Date: Thu, 6 Dec 1990 14:21 MST
Date: Thu, 6 Dec 90 15:24:20 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <8E234DAE5C402A2E@Arizona.edu>
Message-Id: <9012062124.AA07162@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I just thought I'd mention that Norman Azadian's klondike game is
a pretty nicely done piece of software. My son hasn't stopped
playing it since I compiled it this afternoon. He's running it
under a DOS emulator on our Xenix box.
So far, no luck compiling it under Xenix. I'll try to figure
out the problem, and perhaps re-post a Unix version some time in
the near future.
It's probably the best game I've seen done in Icon. And, con-
sidering all the screen processing, it runs pretty fast, too.
-Richard
From icon-group-request@arizona.edu Thu Dec 6 16:49:46 1990
Resent-From: icon-group-request@arizona.edu
Received: from MERLIN.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA19847; Thu, 6 Dec 90 16:49:46 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 16:49 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA17065; Thu, 6 Dec 90 15:42:43
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 6 Dec 1990 16:49 MST
Date: 6 Dec 90 22:46:19 GMT
From: midway!quads.uchicago.edu!goer@handies.ucar.edu (Richard L. Goerwitz)
Subject: sgml stripping
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <A2BFA7AEEC402091@Arizona.edu>
Message-Id: <1990Dec6.224619.22998@midway.uchicago.edu>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Organization: University of Chicago
Mad as this sounds, I occasionally find it expedient simply to
strip out <>-style tags from a SGML-encoded file. Here's a very
simple program to do this. I dunno, but I'd expect that it would
work with the perverted variant of SGML mandated in the U of Chi-
cago guide to electronic manuscripts. I posted this elsewhere,
but since it's Icon code, I figured someone might here might want
to take a look at it.
-Richard
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 12/06/1990 07:11 UTC by goer@sophist.uchicago.edu
# Source directory /u/richard/Stripsgml
#
# existing files will NOT be overwritten unless -c is specified
# This format requires very little intelligence at unshar time.
# "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 3170 -r--r--r-- stripsgml.icn
# 2615 -r--r--r-- stripunb.icn
# 1915 -r--r--r-- readtbl.icn
# 2084 -r--r--r-- slashbal.icn
# 981 -rw-r--r-- README
# 659 -rw-r--r-- Makefile.dist
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= stripsgml.icn ==============
if test -f 'stripsgml.icn' -a X"$1" != X"-c"; then
echo 'x - skipping stripsgml.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting stripsgml.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'stripsgml.icn' &&
X############################################################################
X#
X# Name: stripsgml.icn
X#
X# Title: Strip (or translate) simple SGML tags from a file
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.7
X#
X############################################################################
X#
X# This program, stripsgml, may be used either to strip SGML tags
X# from a file, or to translate them into some other format (or perhaps
X# some combination of the two). Note that it only handles very
X# simple SGML codes, either stripping or translating set strings.
X# This is a VERY simple program, merely intended to satisfy a need
X# many have expressed for being able to remove, or perform simple
X# manipulations on, files containing <>-style tags.
X#
X# In its basic mode, you would simply have stripsgml read the
X# standard input (an SGML-marked file). Stripsgml would then write
X# an SGML-free text on the standard output. Used in this way,
X# stripsgml is just a simple stripping program.
X#
X# If you want some or all of the SGML codes translated into another set
X# of codes, simply create a file in which each line has 1) the name of
X# the SGML code, and then 2) the way you want that code translated on
X# both initialization and completion. The completion specification is
X# optional. Put succinctly, the format is:
X#
X# code initialization completion
X#
X# A tab or colon separates the fields. If you want to use a tab or colon
X# as part of the text (and not as a separator), place a backslash before
X# it. The completion field is optional. There is not currently any way
X# of specifying a completion field without an initialization field.
X#
X# In its translation mode, stripsgml is invoked with one argument (the
X# name of the file containing the translation information). As before,
X# the standard input is expected to contain an SGML encoded file:
X#
X# stripsgml translation_file < SGML-file
X#
X# To the standard output is written a SGML-free text.
X#
X# Note that, if you are translating SGML code into font change or escape
X# sequences, you may get unexpected results. This isn't stripsgml's
X# fault. It's just a matter of how your terminal or WP operate. Some
X# need to be "reminded" at the beginning of each line what mode or font
X# is being used. Note also that stripsgml assumes < and > as delimiters.
X# If you want to put a greater-than or less-than sign into your text,
X# put a backslash before it. This will effectively "escape" the spe-
X# cial meaning of those symbols. There is currently no way to change
X# the default delimiters.
X#
X############################################################################
X#
X# Links: slashbal.icn ./stripunb.icn ./readtbl.icn
X#
X############################################################################
X
X
Xprocedure main(a)
X
X usage := "usage: stripsgml [map-file]"
X *a > 1 & stop(usage)
X
X map_file := open(a[1]) & t := readtbl(map_file)
X
X every line := !&input do
X write(stripunb('<','>',line,&null,&null,t))
X
X # last_k is the stack used in stripunb.icn
X if *\last_k ~= 0 then
X stop("Unexpected EOF encountered. Expecting ", pop(last_k), ".")
X
Xend
SHAR_EOF
true || echo 'restore of stripsgml.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= stripunb.icn ==============
if test -f 'stripunb.icn' -a X"$1" != X"-c"; then
echo 'x - skipping stripunb.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting stripunb.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'stripunb.icn' &&
X############################################################################
X#
X# Name: stripunb.icn
X#
X# Title: Strip unbalanced material
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.3
X#
X############################################################################
X#
X# This routine strips material from a line which is unbalanced with
X# respect to the characters defined in arguments 1 and 2 (unbalanced
X# being defined as bal() defines it, except that characters preceded
X# by a backslash are counted as regular characters, and are not taken
X# into account by the balancing algorithm).
X#
X# One little bit of weirdness I added in is a table argument. Put
X# simply, if you call stripunb() as follows,
X#
X# stripunb('<','>',s,&null,&null,t)
X#
X# and if t is a table having the form,
X#
X# key: "bold" value: outstr("\e[2m", "\e1m")
X# key: "underline" value: outstr("\e[4m", "\e1m")
X# etc.
X#
X# then every instance of "<bold>" in string s will be mapped to
X# "\e2m," and every instance of "</bold>" will be mapped to "\e[1m."
X# Values in table t must be records of type output(on, off). When
X# "</>" is encountered, stripunb will output the .off value for the
X# preceding .on string encountered.
X#
X############################################################################
X#
X# Links: slashbal.icn
X#
X############################################################################
X
Xglobal last_k
Xrecord outstr(on, off)
X
X
Xprocedure stripunb(c1,c2,s,i,j,t)
X
X # NB: Stripunb() returns a string - not an integer (like find,
X # upto).
X
X local lookinfor, bothcs, s2, k
X #global last_k
X initial last_k := list()
X
X /c1 := '<'
X /c2 := '>'
X bothcs := c1 ++ c2
X lookinfor := c1 ++ '\\'
X c := &cset -- c1 -- c2
X
X /s := \&subject | stop("stripunb: No string argument.")
X /i := \&pos | 1
X /j := *s + 1
X
X s2 := ""
X s ? {
X tab(i) | fail
X while s2 ||:= tab(upto(lookinfor)) do {
X if ="\\" & any(bothcs) then {
X &pos+1 > j & (return s2)
X s2 ||:= move(1)
X next
X }
X else {
X &pos > j & (return s2)
X any(c1) |
X stop("stripunb: Unbalanced string, pos(",&pos,").\n",s)
X k := tab(slashbal(c,c1,c2,&null,&null,&null,1)) | tab(0)
X if \t then {
X k ?:= 2(="<", tab(find(">")), =">", pos(0))
X if k ?:= (="/", tab(0)) then {
X compl := pop(last_k) | stop("Unclosed <>, ",&subject)
X if k == ""
X then k := compl
X else k == compl | stop("Incorrectly paired <>, </>.")
X s2 ||:= \(\t[k]).off
X }
X else {
X s2 ||:= \(\t[k]).on
X push(last_k, k)
X }
X }
X }
X }
X s2 ||:= tab(0)
X }
X
X return s2
X
Xend
SHAR_EOF
true || echo 'restore of stripunb.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= readtbl.icn ==============
if test -f 'readtbl.icn' -a X"$1" != X"-c"; then
echo 'x - skipping readtbl.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting readtbl.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'readtbl.icn' &&
X############################################################################
X#
X# Name: readtbl.icn
X#
X# Title: Read user-created stripsgml table
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.1
X#
X############################################################################
X#
X# This file is part of the stripsgml package. It does the job of read-
X# ing option user-created mapping information from a file. The purpose
X# of this file is to specify how each code in a given input text should
X# be translated. Each line has the form:
X#
X# SGML-designator start_code end_code
X#
X# where the SGML designator is something like "quote" (without the quota-
X# tion marks), and the start and end codes are the way in which you want
X# the beginning and end of a <quote>...<\quote> sequence to be transla-
X# ted. Presumably, in this instance, your codes would indicate some set
X# level of indentation, and perhaps a font change. If you don't have an
X# end code for a particular SGML designator, just leave it blank.
X#
X############################################################################
X#
X# Links: stripsgml.icn
X#
X############################################################################
X
X
Xprocedure readtbl(f)
X
X local t, line, k, on_sequence, off_sequence
X
X /f & stop("readtbl: Arg must be a valid open file.")
X
X t := table()
X
X every line := trim(!f,'\t ') do {
X line ? {
X k := tabslashupto('\t:') &
X tab(many('\t:')) &
X on_sequence := tabslashupto('\t:') | tab(0)
X tab(many('\t:'))
X off_sequence := tab(0)
X } | stop("readtbl: Bad map file format.")
X insert(t, k, outstr(on_sequence, off_sequence))
X }
X
X return t
X
Xend
X
X
X
Xprocedure tabslashupto(c,s)
X
X POS := &pos
X
X while tab(upto('\\' ++ c)) do {
X if ="\\" then {
X move(1)
X next
X }
X else {
X if any(c) then {
X suspend &subject[POS:.&pos]
X }
X }
X }
X
X &pos := POS
X fail
X
Xend
SHAR_EOF
true || echo 'restore of readtbl.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= slashbal.icn ==============
if test -f 'slashbal.icn' -a X"$1" != X"-c"; then
echo 'x - skipping slashbal.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting slashbal.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'slashbal.icn' &&
X############################################################################
X#
X# Name: slashbal.icn
X#
X# Title: Bal() with backslash escaping
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.4
X#
X############################################################################
X#
X# I am often frustrated at bal()'s inability to deal elegantly with
X# the common \backslash escaping convention (a way of telling Unix
X# Bourne and C shells, for instance, not to interpret a given
X# character as a "metacharacter"). I recognize that bal()'s generic
X# behavior is a must, and so I wrote slashbal() to fill the gap.
X#
X# Slashbal behaves like bal, except that it ignores, for purposes of
X# balancing, any c2/c3 char which is preceded by a backslash. Note
X# that we are talking about internally represented backslashes, and
X# not necessarily the backslashes used in Icon string literals. If
X# you have "\(" in your source code, the string produced will have no
X# backslash. To get this effect, you would need to write "\\(."
X#
X# BUGS: Note that, like bal() (v8), slashbal() cannot correctly
X# handle cases where c2 and c3 intersect.
X#
X############################################################################
X#
X# Links: none
X#
X############################################################################
X
Xprocedure slashbal(c1, c2, c3, s, i, j)
X
X local twocs, allcs, chr2, count
X
X /c1 := &cset
X /c2 := '('
X /c3 := ')'
X twocs := c2 ++ c3
X allcs := c1 ++ c2 ++ c3 ++ '\\'
X
X /s := \&subject | stop("slashbal: No string argument.")
X /i := \&pos | 1
X /j := *s + 1
X
X count := 0
X s ? {
X tab(i) | fail
X while tab(upto(allcs)) do {
X chr := move(1)
X if chr == "\\" & any(twocs) then {
X chr2 := move(1)
X &pos > j & fail
X if any(c1, chr) & count = 0 then
X suspend .&pos - 2
X if any(c1, chr2) & count = 0 then
X suspend .&pos - 1
X }
X else {
X &pos > j & fail
X if any(c1, chr) & count = 0 then
X suspend .&pos - 1
X if any(c2, chr) then
X count +:= 1
X else if any(c3, chr) then
X count -:= 1
X }
X }
X }
X
Xend
SHAR_EOF
true || echo 'restore of slashbal.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XRe: stripsgml.icn & associated files
X
XThis program is documented in the various source files, most notably
Xstripsgml.icn. Please look them over, even if you are not an Icon
Xprogrammer.
X
XIn order to compile this program, you will need an Icon interpreter
X(or compiler). If you do not have it, get it. It is free, and can
Xbe obtained via ftp from cs.arizona.edu. If you do not have access
Xto the internet, drop a line to the icon-project@arizona.edu, and
Xthey will fill you in on what to do.
X
XIf you are working on a Unix system, you can simply mv Makefile.dist
Xto Makefile, and then make. Users on other systems will need to
Xtype:
X
X icont -o stripsgml readtbl.icn slashbal.icn stripsgml.icn stripunb.icn
X
XAs I said above, see the file stripsgml.icn for more information on how
Xto use this program. This program is not fancy, and handles only the
Xsimplest <>-style markup. It is in no way an attempt to handle the full
Xmetalanguage!
X
X-Richard (goer@sophist.uchicago.edu)
SHAR_EOF
true || echo 'restore of README failed'
rm -f _shar_wnt_.tmp
fi
# ============= Makefile.dist ==============
if test -f 'Makefile.dist' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile.dist (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Makefile.dist (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.dist' &&
XPROGNAME = stripsgml
X
X# Please edit these to reflect your local file structure & conventions.
XDESTDIR = /usr/local/bin
XOWNER = bin
XGROUP = bin
X
XSRC = $(PROGNAME).icn stripunb.icn readtbl.icn slashbal.icn
X
X$(PROGNAME): $(SRC)
X icont -o $(PROGNAME) $(SRC)
X
X# Pessimistic assumptions regarding the environment (in particular,
X# I don't assume you have the BSD "install" shell script).
Xinstall: $(PROGNAME)
X @sh -c "test -d $(DESTDIR) || (mkdir $(DESTDIR) && chmod 755 $(DESTDIR))"
X cp $(PROGNAME) $(DESTDIR)/
X chgrp $(GROUP) $(DESTDIR)/$(PROGNAME)
X chown $(OWNER) $(DESTDIR)/$(PROGNAME)
X @echo "\nInstallation done.\n"
X
Xclean:
X -rm -f *~ .u?
X -rm -f $(PROGNAME)
SHAR_EOF
true || echo 'restore of Makefile.dist failed'
rm -f _shar_wnt_.tmp
fi
exit 0
From goer%sophist@gargoyle.uchicago.edu Thu Dec 6 22:48:10 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from MERLIN.TELCOM.ARIZONA.EDU by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28085; Thu, 6 Dec 90 22:48:10 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu with PMDF#10282; Thu, 6 Dec
1990 22:47 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA05683; Thu, 6 Dec 90 23:47:26 CST
Received: by sophist (4.1/UofC3.1X) id AA07496; Thu, 6 Dec 90 23:50:44 CST
Resent-Date: Thu, 6 Dec 1990 22:47 MST
Date: Thu, 6 Dec 90 23:50:44 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <D4D38E850C402D3C@Arizona.edu>
Message-Id: <9012070550.AA07496@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Richard Goerwitz writes [re Klondike]:
> So far, no luck compiling it under Xenix. I'll try to figure
> out the problem, and perhaps re-post a Unix version some time in
> the near future.
I hope you will. Icon needs a great, portable game.
I've located the problems. Basically they are simply that klondike
a) calls kbhit, which simply can't be done easily and portably from
within Icon under Unix, b) that it calls getch(), c) that it uses
the cursor report request to test for ANSI console conformancy, and
d) that it mixes straight text with screen control codes. These
problems are mainly pretty easy to get around. Kbhit() is called
but once, as I recall. I wrote a getch() implementation for Unix
that will cover (b). Under Unix, (c) isn't necessary (we'll just
check the current environment). I still haven't figured an easy
way to lift screen control codes out of write() functions outputting
straight text, but even in a worst case scenario it will mean just
spending some time doing searches and replaces.
Klondike is indeed a nice game under DOS. Really nicely done. And
this from a guy who claims to be a novice at Icon!
Ron, you'll be the first I'll let know if I do in fact actually get
a Unix version out, since I know you are running Xenix like me, and
also (like me) have some of those blasted magic cookie terminals
sitting around.
-Richard
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Fri Dec 7 10:08:19 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA24517; Fri, 7 Dec 90 10:08:19 -0700
Received: by uwm.edu; id AA00863; Fri, 7 Dec 90 11:08:11 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Fri, 7 Dec 90 08:23:04 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Fri, 7 Dec 1990 08:10 CDT
Date: Fri, 7 Dec 1990 08:09 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Klondike - Neato
To: icon-group@cs.arizona.edu
Message-Id: <23551171406002A9@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
I liked both versions. I got the original PC one running quickly. I liked
the colors. But my chief platform is VAX VMS with VT compatible terminals.
So the ANSI version was welcome. I also took it one step further by using
the ANSI line drawing. For example I replaced "|" with "\e(0x\e(B" and
likewise for the tops and bottoms of cards. I also had to comment out a lot
of getch() and kbhit() which isn't available from VMS, and add read() instead.
Fortunately my wyse terminal also has a 25 line mode.
These added escape sequences may slow things done a little, but the
esthetics are worth it. My daughter loves it, although she gets lazy after
a few minutes and shifts into automatic.
Thanx for the nifty program. I'm interested in game playing heuristics.
I'd like to post another one I use on my daughter. It's call Spelling test.
I type the words into a file. This file is then redirected into the spelltest
program which asks for words. It assumes that you have the words on another
sheet as well from which the test is administered. The words can be given in
any order. The masters and answers are then sorted and compared in parallel.
It works almost like magic as long as the words are not too lexically similar
and the student isn't too bad of a speller. Perhaps the parallel checking might
have been done better with coexpressions, but I'm not skilled with them.
#
# SPELLTEST.ICN 11/26/90 BY TENAGLIA
#
# THIS SIMPLE PROGRAM ADMINISTERS A SPELLING TEST. THE WORDS SHOULD BE LISTED
# ONE PER LINE IN AN ANSWER FILE. THE TEACHER CAN ISSUE THE WORDS IN ANY ORDER
# AS THE TRIES AND ANSWERS ARE FINALY SORTED AND COMPARED IN PARALLEL. THIS
# SORT OF IMPLIES THAT THE WORDS SHOULD NOT BE TOO LEXICALLY ALIKE. THE GOOF
# UPS AND SCORES ARE OUTPUT AT THE END OF THE TEST. THE ANSWER FILE IS PIPED
# INTO STDIN. USAGE : ICONX SPELLTEST <ANSWERS
#
global tty
procedure main()
answers := [] # THE CORRECT WORDS LOADED HERE
words := [] # THE STUDENTS TRIES STORED HERE
tally := table(0) # SCORE KEEPER
tty := open("tt:","b")
#
# INITIAL DIALOG
#
write("\e[2J\e[H\e#3Spelling Test")
write("\e#4Spelling Test")
write("\nLoading spelling words...")
while put(answers,map(read()))
write("Spelling words loaded. Commencing test. ",*answers," problems.\n")
#
# ADMINISTER THE TEST
#
every i := 1 to *answers do
put(words,map(input("\e#6" || i || ". ")))
#
# SORT FOR CORRECTING
#
first := sort(answers)
second := sort(words)
#
# CORRECT THE RESULTS
#
every i := 1 to *first do
{
result := if first[i] == second[i] then "correct" else "incorrect"
tally[result] +:= 1
(first[i] == second[i]) | write("\e[1;5m",second[i],"\e[m is wrong. It should have been spelled \e[1;5m",first[i],"\e[m")
}
#
# SUMMARY OF PERFORMANCE
#
write("\n",tally["incorrect"]," were incorrect.")
write(tally["correct"]," were correct out of ",*answers," words.")
write("Final score is ",tally["correct"]*100/(*answers),"%.")
end
#
# THIS PROCEDURE TAKES A PROMPTED STRING INPUT
#
procedure input(prompt)
writes(prompt)
return read(tty)
end
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From goer%sophist@gargoyle.uchicago.edu Sat Dec 8 03:50:54 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02456; Sat, 8 Dec 90 03:50:54 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Sat, 8 Dec 90 03:50 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA04481; Sat, 8 Dec 90 04:49:50 CST
Received: by sophist (4.1/UofC3.1X) id AA08404; Sat, 8 Dec 90 04:53:09 CST
Resent-Date: Sat, 8 Dec 90 03:50 MST
Date: Sat, 8 Dec 90 04:53:09 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike -> unix (preliminary)
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F237BB2DDBC3403C42@Arizona.edu>
Message-Id: <9012081053.AA08404@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
OK, I hacked this together tonight for fun. It's not perfect.
The saving mechanism isn't working quite right, and when com-
piled under DOS the help screen needs work. I did this so that
I could run the executable under Xenix at an ANSI console. It
will probably work on any Unix variant that implements the -g
option for stty, and which looks remotely USG. Who knows, it
might work under BSD. Definitely not well tested, though. I
kind of hoped that others who had wanted this thing up and run-
ning under Unix would fix it up some more in the usual hand-me-
down fashion....
Five-part shar follows in fairly small pieces.
-Richard
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 12/08/1990 11:18 UTC by goer@sophist.uchicago.edu
# Source directory /u/richard/Klondike
#
# existing files will NOT be overwritten unless -c is specified
# This format requires very little intelligence at unshar time.
# "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 20981 -r--r--r-- klondike.icn
# 17168 -r--r--r-- kloncon.icn
# 15873 -r--r--r-- klonsub.icn
# 12240 -r--r--r-- itlib.icn
# 8538 -r--r--r-- getchlib.icn
# 4418 -r--r--r-- iscreen.icn
# 4513 -rw-r--r-- klondike.man
# 477 -rw-r--r-- README
# 707 -rw-r--r-- Makefile.dist
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= klondike.icn ==============
if test -f 'klondike.icn' -a X"$1" != X"-c"; then
echo 'x - skipping klondike.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting klondike.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'klondike.icn' &&
X############################################################################
X#
X# Name: klondike.icn
X#
X# Title: klondike card game
X#
X# Author: Norman H. Azadian, ported to Unix by Richard Goerwitz
X#
X# Version: 1.5 (beta)
X#
X############################################################################
X#
X# klondike.icn 900720 NHA
X# The Klondike version of Solitaire.
X# Requires ANSI.SYS (or NANSI.SYS) screen driver and a 25-line display.
X#
X# TO FIX:
X#
X#
X# TO DO:
X#
X# - Use space to step to next non-thumb move, and enter to do it ???
X# - Implement an heuristic to discover optimal play strategy.
X#
X# UNIX VERSION: This Unix port of the MS-DOS game classifies as some-
X# thing of a hack. It's what I could do in an evening. Don't bug me
X# about it :-). -RLG
X#
X############################################################################
X#
X# Links:
X#
X# See also: kloncon.icn, klonsub.icn
X#
X############################################################################
X
Xlink kloncon #console I/O
Xlink klonsub #general subroutines
X
Xrecord card(suit, rank) #suit is 1..4, rank is 1..13
X
X# variables
Xglobal deckUp, deckDown, stackUp, stackDown #collections of card
Xglobal pile #ace piles - top rank only
Xglobal ops #list of all operations done
Xglobal debugging, automaticAce #command-line flags
Xglobal invisible, clicking #visual, audible feedback
Xglobal firstSeed, lastSeed #&random remembered
Xglobal totalGames, totalAces #ace pile statistics
X
X
X# a u t o m a t i c 1
X# Do 1 move, thumbing as necessary to achieve it.
X# Fails if there is nothing useful left to do.
X# This is an internal routine that doesn't worry at all about the user.
Xprocedure automatic1 ()
Xlocal s, thumbCount
X thumbCount := 0
X while thumbCount <= ((*deckUp + *deckDown + 2) / 3) do {
X if s := suggest() then {
X push (ops, _move ("M" || s || "0"))
X thumbCount := 0
X return;
X } else { #no good move found -- thumb
X if (*deckUp = 0) & (*deckDown = 0) then
X fail #no cards left to thumb through
X push (ops, s := thumb())
X if 2 < *s then
X return #must have turned up an Ace
X thumbCount +:= 1
X }
X }
Xend #automatic1
X
X
X# a u t o m a t i c
X# Run the game, as far as possible, untouched by human hands
X# This is an internal routine that only worries a little about the user.
X# Returns when either there is nothing useful left to do or a key is struck.
Xprocedure automatic ()
Xlocal s, thumbCount
X thumbCount := 0
X repeat {
X if \isDOS then {
X if kbhit () then
X return #stopped by human intervention
X }
X if pile[1] = pile[2] = pile[3] = pile[4] = 13 then
X return #victory
X automatic1 () | return
X }
Xend #automatic
X
X
X# u a u t o m a t i c
X# Play this hand automatically, untouched by human hands.
X# This is the fuction that interacts with the user.
Xprocedure uautomatic ()
X writes ("utomatic")
X automatic()
X if \isDOS then {
X if kbhit() then
X if getch() == "\0" then getch()
X }
Xend #uautomatic
X
X
X# u c o n t i n u o u s
X# Plays automatic games -- forever (or until any keystroke)
Xprocedure ucontinuous()
X writes ("ontinuous")
X repeat {
X writeInfo (string(totalGames) || " " || string(totalAces))
X automatic()
X if \isDOS & kbhit() then {
X if getch() == "\0" then #eat stopping char(s)
X getch()
X return
X } else
X totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
X totalGames +:= 1
X if \isUNIX then {
X writeCursor (18, 65)
X iputs(getval("ce"))
X writes ("Continue? ")
X until (s := getCmdChar ())
X map(s) == "n" | next
X return
X }
X lastSeed := newGame()
X }
Xend #ucontinuous
X
X
X# u h e l p
X# Provide command summary for user, plus statistics to date, if any.
Xprocedure uhelp ()
X if \isDOS then
X write (VclearAll, Vnormal)
X else if \isUNIX then {
X normal (); clear ()
X }
X writeCursor (2, 1)
X writes ("Klondike version 1.5 901126 NHA", repl(" ",8), &version)
X writeCursor (5, 1)
X writes ("The following commands are available:")
X writeCursor (8, 8)
X bwrite ("^L\tre-draw", " screen")
X writeCursor (9, 8)
X if \isDOS then
X bwrite ("A\tAutomatic", " mode -- plays 1 game by itself until any key is hit")
X else if \isUNIX then
X bwrite ("A\tAutomatic", " mode -- plays 1 game by itself.")
X writeCursor (10, 8)
X bwrite ("B\tBoss", " key for when you-know-who visits")
X writeCursor (11, 8)
X if \isDOS then
X bwrite ("C\tContinuous", " mode -- plays games continuously until any key hit")
X else if \isUNIX then
X bwrite ("C\tContinuous", " mode -- plays games by itself")
X writeCursor (12, 8)
X bwrite ("H,?\tHelp", ", this help screen")
X writeCursor (13, 8)
X bwrite ("M\tMove", " card (or stack) from Deck/Stack to Stack/Ace pile")
X writeCursor (14, 8)
X bwrite ("Q\tQuit", " this game")
X writeCursor (15, 8)
X bwrite ("S\tSuggest", " (another) possible move")
X writeCursor (16, 8)
X bwrite ("T\tThumb", " through the deck")
X writeCursor (17, 8)
X bwrite ("U\tUndo", " -- back up one move")
X writeCursor (18, 8)
X bwrite ("ESC\tEscape", " -- abort current command")
X writeCursor (19, 9)
X if \debugging then
X bwrite ("Z\tDebug")
X
X writeCursor (20, 1)
X if totalGames ~= 0 then
X writes ("totalGames = ", totalGames, " totalAces = ", totalAces,
X " average = ", real(totalAces) / real(totalGames))
X writeCursor (23, 1)
X bwrite ("", "Press any key to resume game")
X writeCursor (24, 1)
X if getch() == "\0" then getch()
X refreshScreen ()
Xend #uhelp
X
X
X# b w r i t e
X# Boldface first arg in 1-4 string-arg procedure.
Xprocedure bwrite(a, b[])
X if \isDOS then
X writes (Vbold)
X else if \isUNIX then
X emphasize()
X writes(a)
X if \isDOS then
X writes (Vnormal)
X else if \isUNIX then
X normal()
X every writes(\!b)
X return
Xend
X
X
X# u m o v e
X# Move a card from deck to stack, or from stack to ace pile,
X# or move a stack to another stack.
X# Parameter is the source [1-7 or D] or &null to indicate that "M" was used
X# and therefore source should be gathered from the keyboard.
X# Fails if indicated move is not possible
X# This is the routine that interacts with the user.
Xprocedure umove (src)
Xlocal dst, c, op, moved
X if \src then {
X if \isDOS then
X writes ("\bMove ", Vbold, src)
X else if \isUNIX then {
X writes ("\bMove ")
X emphasize ()
X writes (src)
X }
X }
X else {
X if \isDOS then
X writes ("ove " || Vbold)
X else if \isUNIX then {
X writes ("ove ")
X emphasize ()
X }
X until (src := getCmdChar ())
X if src == ESC then return
X }
X if src == "D" then {
X if *deckUp = 0 then fail
X } else {
X if not any ('1234567', src) then fail
X if *stackUp[src] = 0 then fail
X writeStackNumber (src, Vblink)
X }
X
X if \isDOS then
X writes (Vnormal || " to " || Vbold)
X else if \isUNIX then {
X normal ()
X writes (" to ")
X emphasize ()
X }
X until (dst := getCmdChar ())
X if src ~== "D" then writeStackNumber (src, Vnormal)
X if dst == ESC then return
X if not any ('A1234567', dst) then fail
X if dst == src then fail
X
X return push (ops, _move("M" || src || dst || "0"))
Xend #umove
X
X
X# s u g g e s t
X# Find a (reasonable) possible move in this situation
X# This is the internal routine.
Xprocedure suggest ()
Xlocal i, j, k, c
X #look at deckUp to see if the top card fits on a pile
X if c := deckUp[1] then
X if c.rank = (pile[c.suit] + 1) then
X suspend "DA"
X #look at deckUp to see if the top card fits on a stack
X if c := deckUp[1] then
X every i := 1 to 7 do
X if fitOnStack (c, i) then
X suspend "D" || string(i)
X #look at each stack to see if top card can be put on ace pile
X every i := 1 to 7 do
X if c := stackUp[i][-1] then #top card
X if c.rank = (pile[c.suit] + 1) then
X suspend string(i) || "A"
X #look at each stack to see if something can be (reasonably) moved
X every i := 7 to 1 by -1 do
X every j := 1 to 7 do
X if fitOnStack (stackUp[i][1], j) then {
X if (0 < *stackDown[i]) then
X suspend string(i) || string(j)
X else {
X # possibility, but since there are no cards hidden under
X # this pile, we reject it UNLESS there are no empty slots
X # AND one of the following is true:
X # 1) deckUp[1].rank = 13
X # 2) there is a king with cards hidden beneath it
X c := 0 #number of empty stacks
X every k := 1 to 7 do
X if *stackUp[k] = 0 then c +:= 1
X if c = 0 then
X if (deckUp[1].rank = 13) |
X (every k := 1 to 7 do
X if (stackUp[k][1].rank = 13) &
X (0 < *stackDown[k]) then
X break #success
X )
X then
X suspend string(i) || string(j)
X }
X }
X #punt
X fail
Xend #suggest
X
X
X# u s u g g e s t
X# Suggest a (reasonable) possible move in this situation.
X# Repeated invocations produce successive possibilities, until the
X# only thing left to do is Thumb. After this, it cycles around to the start.
Xprocedure usuggest (another)
Xstatic suggestions, i
Xlocal s, ss
X writes ("uggest")
X if another = 0 then {
X suggestions := [] #generate a new list of suggestions
X every put (suggestions, suggest())
X i := 0
X }
X if ss := suggestions[i+:=1] then {
X s := "Move " || if ss[1] == "A" then "Ace"
X else if ss[1] == "D" then "Deck"
X else ss[1]
X s ||:= " to " || if ss[2] == "A" then "Ace" else ss[2]
X writeInfo (s)
X } else {
X writeInfo ("Thumb")
X i := 0
X }
Xend #usuggest
X
X
X# u t e r m i n a t e
X# Parameter should be non-zero if termination is due to complete success.
X# Returns success to quit this game and start another.
X# Returns failure to just continue this game.
X# If program termination is wished, that is done right here.
Xprocedure uterminate (victory)
Xlocal s
X if \victory then {
X totalAces +:= 52
X pile[1] := pile[2] := pile[3] := pile[4] := 0 #prevent victory loops
X writeCursor (12, 22)
X if \isDOS then
X writes (Vbold, Vblink, "Congratulations -- You've WON !!!", Vnormal)
X else if \isUNIX then {
X emphasize ()
X writes ("Congratulations -- You've WON !!!")
X normal ()
X }
X } else
X writes ("uit")
X if \isDOS then
X writeInfo (Vbold || "Another game? ")
X else if \isUNIX then
X writeInfo ("Another game? ")
X until (s := getCmdChar ())
X if s == ESC then fail() #didn't really want to quit anyway
X if s == "Y" then return #please start a new game
X if s ~== "N" then return complain ()
X
X #program termination requested
X if \isDOS then
X writes ("\33[=7h", Vnormal) #set cursor wrap mode, normal attr
X else if \isUNIX then
X normal () & clear ()
X totalGames +:= 1
X if /victory then
X totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
X writeCursor (2, 1)
X writes (VclearAll, "In ", totalGames, " games, you put ", totalAces,
X " cards on the ace piles")
X writeCursor (3, 1)
X write ("average = ", real(totalAces) / real(totalGames), " per game")
X writeCursor (5, 1)
X if \isUNIX then reset_tty()
X exit ()
Xend #uterminate
X
X
X# u d e b u g
X# Additional commands to support the implementer.
Xprocedure udebug ()
Xlocal s, d, c, name
X if not \debugging then return complain()
X writes ("\bDebug ")
X until (s := getCmdChar ())
X case s of {
X ESC : fail
X "A" : {
X writes ("gain")
X &random := lastSeed
X writeCursor (23, 1)
X write (Vbold, "&random set. Quit to play this game again.",
X Vnormal, VclearEOL)
X }
X "D" : display()
X "H"|"?" : {
X writes (if s == "?" then "\bhelp" else "elp")
X writeCursor (23, 1)
X write (Vbold,
X "Again, Dump, Options, Move, Peek{1-7UD}, Restore, Save, Toggle{ACT}.",
X Vnormal, VclearEOL)
X }
X "M" : {
X writes ("ove ")
X until (s := getCmdChar ()) #Source
X if s == ESC then fail
X if s == "A" then fail
X until (d := getCmdChar ()) #Destination
X if d == ESC then fail
X if d == s then fail
X if not any('1234567', d) then fail
X if s == "D" then {
X if *deckUp = 0 then fail
X put (stackUp[d], get(deckUp))
X writeDeckUp ()
X writeStack (d)
X push (ops, "MD" || d || "0")
X } else {
X c := "123456789abcdef"[*stackUp[s]]
X moveStack (s, d)
X push (ops, "M" || s || d || c)
X }
X }
X "O" : {
X writes ("ptions")
X writeCursor (23, 1)
X write (Vbold,
X if \automaticAce then "AutomaticAce " else " ",
X if \clicking then "Clicking " else " ",
X " &trace=", &trace,
X " seeds=", firstSeed, ",", lastSeed, Vnormal, VclearEOL)
X }
X "P" : {
X writes ("eek ")
X until (s := getCmdChar ())
X if s == ESC then fail
X writeCursor (23, 1)
X writes (VclearEOL, Vnormal)
X if any('1234567', s) then showList (stackDown[s])
X else if s == "D" then showList (deckDown)
X else if s == "U" then showList (deckUp)
X else complain ()
X }
X "R" : {
X writes ("estore")
X until (s := getCmdChar ())
X if s == ESC then fail
X name := "klondike.sv" || s
X if (d := restoreState(name)) then {
X refreshScreen()
X writeCursor (23, 1)
X write (Vbold, "Restored position from file ", name,
X " of ", d, Vnormal, VclearEOL)
X } else {
X writeCursor (23, 1)
X write (Vblink, "Can't restore from file ", name, ".",
X Vnormal, VclearEOL)
X }
X }
X "S" : {
X writes ("ave ")
X until (s := getCmdChar ())
X if s == ESC then fail
X name := "klondike.sv" || s
X writeCursor (23, 1)
X if saveState (name) then
X write (Vbold, "Position saved in file ",name,
X Vnormal, VclearEOL)
X else
X write (Vblink, "Can't save in file ", name, ".",
X Vnormal, VclearEOL)
X }
X "T" : {
X writes ("oggle ")
X until (s := getCmdChar ())
X if s == ESC then fail
X case s of {
X "A" : automaticAce := if \automaticAce then &null
X else 1
X "C" : clicking := if \clicking then &null else 1
X "T" : &trace := if &trace = 0 then -1 else 0
X default : complain ()
X } #case for Toggle
X }
X default : complain ()
X } #case for Debug command
Xend #udebug
X
X
X# u b o s s
X# Cheese it, the Fuzz.
X# Quick -- clear the screen and save the state in a file.
Xprocedure uboss ()
X writes ("oss")
X if \isDOS then {
X writes("\33[=7h", VclearAll, "C>") #set cursor-wrap mode, look innocent
X saveState ("klondike.sav")
X }
X else if \isUNIX then {
X normal()
X clear()
X saveState("~/.klondike.sav")
X reset_tty()
X }
X exit ()
Xend #uboss
X
X
X
X# m a i n
Xprocedure main (av)
Xlocal s, prevsCmd, maxGames, f_nam
X
X # set defaults
X automaticAce := 1 # automatic ace handling
X clicking := 1 # give audible feedback
X debugging := &null # no debugging allowed
X invisible := &null # let's see the action
X maxGames := &null # interactive mode
X &random := map (&clock, ":", "0") # randomize the seed
X
X # deal with command-line parameters
X while s := get (av) do
X case map (s, &lcase, &ucase) of {
X "-A" : automaticAce := &null #disable automatic ace handling
X "-B" : maxGames := get (av) #batch mode, this many games
SHAR_EOF
true || echo 'restore of klondike.icn failed'
fi
echo 'End of part 1'
echo 'File klondike.icn is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0
From goer%sophist@gargoyle.uchicago.edu Sat Dec 8 03:51:42 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02492; Sat, 8 Dec 90 03:51:42 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Sat, 8 Dec 90 03:50 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA04503; Sat, 8 Dec 90 04:50:40 CST
Received: by sophist (4.1/UofC3.1X) id AA08417; Sat, 8 Dec 90 04:53:59 CST
Resent-Date: Sat, 8 Dec 90 03:51 MST
Date: Sat, 8 Dec 90 04:53:59 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike, part 02 of 05
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F2379D404493403944@Arizona.edu>
Message-Id: <9012081053.AA08417@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is klondike.02 (part 2 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file klondike.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping klondike.icn'
else
echo 'x - continuing file klondike.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'klondike.icn' &&
X "-C" : clicking := &null #run silent
X "-D" : debugging := 1 #grant all sorts of perqs
X "-R" : &random := get (av) #unrandomize
X default : {write ("klondike [-ACD] [-B gameCount] [-R randomSeed]")
X if \isUNIX then reset_tty()
X stop("klondike: bogus option ", s) }
X }
X
X totalGames := totalAces := 0
X
X if \maxGames then {
X # In Batch mode there is absolutely no console I/O.
X # The requested number of games is played
X # and the average result is printed on the standard output.
X invisible := 1
X clicking := &null
X totalGames := maxGames
X while 0 <= (maxGames -:= 1) do {
X newGame ()
X while automatic1 () #don't allow user to interrupt
X totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
X }
X write (real(totalAces) / real(totalGames))
X if \isUNIX then reset_tty()
X exit ()
X }
X
X
X initConstants() #for console I/O
X firstSeed := &random #initial seed
X
X lastSeed := newGame ()
X #if last game terminated via the Boss key, then restore it now
X if \isDOS then
X f_nam := "klondike.sav"
X else if \isUNIX then
X f_nam := "~/.klondike.sav"
X if restoreState (f_nam) then {
X refreshScreen ()
X writeInfo ("Game restored")
X close (open (f_nam, "c")) #truncate boss save file
X }
X
X
X repeat { #game loop
X prevsCmd := "x" #anything but "S"uggest
X
X #respond to user input
X repeat { #command loop
X writeCursor (18, 65)
X if \isDOS then
X writes (VclearEOL || Vnormal || "> ") #clear command line
X else if \isUNIX then {
X iputs (getval("ce"))
X normal ()
X writes ("> ") #clear command line
X }
X if pile[1] = pile[2] = pile[3] = pile[4] = 13 then
X if uterminate (1) then break # VICTORY!
X s := getCmdChar ()
X writeInfo ("") #clear info line
X writeCursor (18, 68)
X case s of {
X "?"|"H" : uhelp()
X "1"|"2"|"3"|"4"|"5"|"6"|"7"|"D" :
X if not umove(s) then complain()
X "A" : uautomatic() #look Ma, no hands!
X "B" : uboss() #bail out -- quick
X "C" : ucontinuous() #no hands, forever
X "M" : if not umove(&null) then complain()
X "Q" : if uterminate(&null) then break #new game
X "S" : usuggest (if s == prevsCmd then 1 else 0)
X "T" : { writes("humb"); push(ops, thumb()) }
X "U" : undo()
X "Z" : udebug()
X "\^L" : refreshScreen()
X ESC : s #do nothing here
X default : complain()
X } #case
X prevsCmd := s
X } #repeat command
X totalAces +:= pile[1] + pile[2] + pile[3] + pile[4]
X totalGames +:= 1
X lastSeed := newGame ()
X } #repeat game
Xend #main
SHAR_EOF
echo 'File klondike.icn is complete' &&
true || echo 'restore of klondike.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= kloncon.icn ==============
if test -f 'kloncon.icn' -a X"$1" != X"-c"; then
echo 'x - skipping kloncon.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting kloncon.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'kloncon.icn' &&
X############################################################################
X#
X# Name: kloncon.icn
X#
X# Title: klondike console interface routines
X#
X# Author: Norman H. Azadian
X#
X# Version: 1.3
X#
X############################################################################
X#
X# kloncon.icn 901029 NHA
X# Console interface routines for Klondike
X# Requires ANSI.SYS (or NANSI.SYS) screen driver and a 25-line display.
X#
X# TO FIX:
X#
X#
X# TO DO:
X#
X# - termcap for portability ??
X# - click for each card moved in a stack ?
X#
X############################################################################
X#
X# Links:
X#
X# See also: klondike.icn, klonsub.icn
X#
X############################################################################
X
X
X# constants
Xglobal suitID #suit identification chars
Xglobal isDOS # 1 when running under DOS
Xglobal isUNIX # 1 when running under UNIX
Xglobal isXENIXconsole # 1 if XENIX ansi console
Xglobal monochrome # 1 when running Black&White
X# Video control strings (ANSI.SYS)
Xglobal ESC
Xglobal Vnormal, Vreverse, Vblink, Vbold, VclearAll, VclearEOL, Vbell
Xglobal color #list of suit color strings
X
X
X# i n i t C o n s t a n t s
X# Initialize the program "constants". These are actually variables that
X# are set just once at the beginning of the world.
Xprocedure initConstants ()
Xlocal i
Xlocal Vred, Vblack #suit color strings
X
X if \invisible then return
X
X isUNIX := find("UNIX",&features)
X isDOS := find("MS-DOS",&host)
X isXENIXconsole := 1(find("XENIX",&host), find("ansi"|"li",getname()))
X
X if \isDOS then {
X #ensure that we are dealing with an ANSI-compatible screen
X writes ("\33[6n") #request cursor position report
X #NOTE that the first character to match should be an ESCape.
X #Unfortunately, reads() seems to eat that character
X match ("[", reads (&input, 8)) |
X stop ("Klondike: requires (N)ANSI.SYS screen driver")
X
X i := ord (Peek([16r40, 16r49])) #BIOS display mode byte
X case i of {
X 2 : monochrome := 1
X 3 : monochrome := &null #living color
X 7 : monochrome := 1
X default : {
X stop ("Klondike: unknown display mode ", i)
X }
X }
X } else
X monochrome := 1
X
X if \isDOS then {
X ESC := "\33" #escape character
X VclearAll := "\33[2J" #also homes cursor
X VclearEOL := "\33[K"
X Vnormal := "\33[0m"
X Vbold := "\33[1m"
X Vblink := "\33[5m"
X Vreverse := "\33[7m"
X Vbell := "\^G"
X if \monochrome then {
X Vred := Vnormal
X Vblack := Vreverse
X } else {
X Vred := "\33[0;47;31m" # "extra" 0 seems to be necessary
X Vblack := "\33[0;47;30m"
X }
X }
X else if \isUNIX then {
X # Check terminal size.
X 24 < getval("li") < 29 & 79 < getval("co") < 85 |
X { reset_tty(); stop("klondike: terminal must be 80x25.") }
X ESC := "\e"
X VclearAll := getval("cl")
X Vnormal := getval("se") || (getval("ue") | "") |
X { reset_tty(); stop("klondike: terminal must have standout mode.") }
X VclearEOL := Vnormal || getval("ce")
X Vbold := getval("so")
X Vblink := getval("us")
X Vreverse := getval("so")
X Vbell := "\^G"
X# color not implemented for UNIX
X# if \monochrome then {
X Vred := Vnormal
X Vblack := Vreverse
X# } else {
X# Vred := "\33[0;47;31m" # "extra" 0 seems to be necessary
X# Vblack := "\33[0;47;30m"
X# }
X }
X else
X stop("Klondike: OS not supported.")
X
X # Suits are: 1=Hearts, 2=Diamonds, 3=Clubs, 4=Spades
X suitID := if \isDOS then "\3\4\5\6" else "HDCS"
X color := [Vred, Vred, Vblack, Vblack]
Xend #initConstants
X
X
X# i n i t S c r e e n
X# Initialize output and write the fixed parts of the screen.
X# initConstants() must have been called earlier.
Xprocedure initScreen ()
Xlocal i
Xstatic vertical
Xinitial {
X vertical := if \isDOS then "\272" else "|"
X}
X
X if \invisible then return
X if \isDOS then {
X if \monochrome then writes ("\33[=2h") #25x80 B&W text mode
X else writes ("\33[=3h") #25x80 color text mode
X writes (VclearAll, "\33[=7l") #clear screen, prevent wrap
X }
X else if \isUNIX then {
X iputs(getval("se"))
X iputs(getval("ue"))
X clear()
X }
X
X every i := 1 to 7 do
X writeStackNumber (i, Vnormal)
X every i := 2 to 25 do {
X if \isDOS then
X writes ("\33[",i,";64H", vertical)
X else if \isUNIX then {
X iputs(igoto(getval("cm"), 64, i))
X writes (vertical)
X }
X }
X if \isDOS then
X writes ("\33[2;64H\311\315\315\315\315SOLITAIRE\315\315\315\315")
X else if \isUNIX then {
X iputs(igoto(getval("cm"), 64, 2))
X writes ("=====SOLITAIRE====")
X }
Xend #initScreen
X
X
X# w r i t e S t a c k N u m b e r
X# Write the indicated stack number with the specified video attribute.
X# Cursor position is preserved -- WARNING: THIS IS NOT NESTABLE.
Xprocedure writeStackNumber (num, attr)
X if \invisible then return
X if \isDOS then
X writes (ESC, "[s") #save cursor position
X writeCursor (1, [2,11,20,29,38,47,56][num])
X if \isDOS then {
X writes (attr, num, Vnormal)
X writes (ESC, "[u") #restore cursor position
X }
X else if \isUNIX then {
X iputs(attr); writes(num); iputs(Vnormal)
X writeCursor (18, 73)
X }
Xend #writeStackNumber
X
X
X# w r i t e C u r s o r
X# Position the cursor to row,col.
X# Screen origin (top left corner) is row=1 and col=1.
Xprocedure writeCursor (row, col)
X if /invisible then {
X if \isDOS then
X writes ("\33[", row, ";", col, "H")
X else if \isUNIX then
X iputs(igoto(getval("cm"), col, row))
X }
Xend #writeCursor
X
X
X# w r i t e F r o n t
X# Displays an image of the specified card fronts at the specified spot.
X# WARNING: this eats the list that you provide -- pass a copy() if you care!!
X# Top left corner of the first card will be placed at the specified position.
X# Successive cards are displayed two rows higher (lower position on the screen).
X# Cursor need not be in any particular position before this, and is left
X# in a random position afterwards. Video is always left normal (not reversed).
X# Cards are 7 columns wide by 5 rows tall.
X# With 25 rows, we can put 12 cards in a stack (assuming we start in row 2).
X# But if there are 11 in the stack we can only display 4 rows of the top card.
X# If there are 12 cards, we can only display 2 rows of the topmost card.
X##We can only write a row at a time due to a problem with ANSI col 80 handling.
Xprocedure writeFront (cardlist, row, col)
Xlocal suit, rank, card
Xstatic vertical, topHorizontal, bottomHorizontal
Xinitial {
X if \isDOS then {
X vertical := "\263"
X topHorizontal := "\332\304\304\304\304\304\277"
X bottomHorizontal := "\300\304\304\304\304\304\331"
X } else {
X vertical := "|"
X topHorizontal := "-------"
X bottomHorizontal := "-------"
X }
X}
X if \isDOS then {
X while card := get(cardlist) do {
X #first 2 rows of card
X writeCursor (row+0, col);
X writes (Vreverse, topHorizontal)
X writeCursor (row+1, col);
X writes (vertical, color[card.suit], "A23456789TJQK"[card.rank],
X suitID[card.suit], Vreverse, " ", vertical)
X if (*cardlist = 0) & (row < 24) then {
X #next 2 rows of top card unless it's the 12th card on the stack
X writeCursor (row+2, col);
X writes (Vreverse, vertical, " ", vertical)
X writeCursor (row+3, col);
X writes (vertical," ",color[card.suit],"A23456789TJQK"[card.rank],
X suitID[card.suit], Vreverse, vertical)
X if row < 22 then {
X #last row of card unless it's the 11th on the stack
X writeCursor (row+4, col);
X writes (bottomHorizontal)
X }
X }
X row +:= 2
X }
X writes (Vnormal)
X }
X else if \isUNIX then {
X if (row = 21, col > 65, getval("li") = 25, \getval("am")) then
X row -:= 1
X while card := get(cardlist) do {
X #first 2 rows of card
X writeCursor (row+0, col);
X emphasize (); writes (topHorizontal)
X writeCursor (row+1, col);
X writes (vertical, color[card.suit], "A23456789TJQK"[card.rank],
X suitID[card.suit]); emphasize (); writes (" ", vertical)
X if (*cardlist = 0) & (row < 24) then {
X #next 2 rows of top card unless it's the 12th card on the stack
X writeCursor (row+2, col);
X emphasize (); writes (vertical, " ", vertical)
X writeCursor (row+3, col);
X writes (vertical," ",color[card.suit],"A23456789TJQK"[card.rank],
X suitID[card.suit]); emphasize (); writes (vertical)
X if row < 22 then {
X #last row of card unless it's the 11th on the stack
X writeCursor (row+4, col);
X writes (bottomHorizontal)
X }
X }
X row +:= 2
X }
X normal ()
X }
Xend #writeFront
X
X
X# w r i t e B a c k
X# Puts an image of the back of a card at the specified spot on the screen.
Xprocedure writeBack (row, col)
Xstatic backLine
Xinitial {
X backLine := repl (if \isDOS then "\260" else "#", 7)
X}
X if \invisible then return
X if (row = 21, col > 65, \isUNIX, getval("li") = 25, \getval("am")) then
X row -:= 1
X writeCursor (row+0, col); writes (backLine)
X writeCursor (row+1, col); writes (backLine)
X writeCursor (row+2, col); writes (backLine)
X writeCursor (row+3, col); writes (backLine)
X writeCursor (row+4, col); writes (backLine)
Xend #writeBack
X
X
X# w r i t e B l a n k
X# Blanks a card-sized area at the specified spot on the screen.
Xprocedure writeBlank (row, col)
Xstatic blankLine
Xinitial {
X blankLine := repl (" ", 7)
X}
X if \invisible then return
X if (row = 21, col > 65, \isUNIX, getval("li") = 25, \getval("am")) then
X row -:= 1
X writeCursor (row+0, col); writes (blankLine)
X writeCursor (row+1, col); writes (blankLine)
X writeCursor (row+2, col); writes (blankLine)
X writeCursor (row+3, col); writes (blankLine)
X writeCursor (row+4, col); writes (blankLine)
Xend #writeBlank
X
X
X# w r i t e S t a c k
X# Display the specified stack. Left end is bottom of stackUp, top of stackDown.
X# Stacks start in row 2, column1; with 2 columns between stacks.
X# last[] holds, for each stack, the total number of visible cards
X# on that stack as of the last time writeStack() was called. This allows
X# us to simply draw (or erase) the cards that have been added (or subtracted).
X# By special arrangement, this routine can be called with a negative stack
X# number! This is a hint that our idea of what is on the display is actually
X# wrong, and therefore the entire stack needs to be re-displayed. This can
X# happen in two situations: 1) in refreshScreen(), the entire screen is cleared
X# before calling writeStack(); 2) in undo() when undoing a move between
X# stacks, the bottom card needs to be changed, although the normal algorithm
X# would consider that it is already correctly displayed. Note that in neither
X# case is the stack shrinking, therefore we don't need to worry about erasing
X# any cards that were displayed last time.
Xprocedure writeStack (n)
Xlocal row, col, s
Xstatic last, blankLine, firstRow, lastRow
Xinitial {
X last := [0,0,0,0,0,0,0]
X blankLine := repl (" ", 7)
X firstRow := [2,4,6,8,10,12,14,16,18,20,22,24] #first row of a card
X lastRow := [6,8,10,12,14,16,18,20,22,24,25,25] #last row of a card
X}
X if \invisible then return
X if n < 0 then {
X n := -n
X last[n] := 0 #force complete re-write
X }
X
X col := 1 + ((n -1) * 9) #leftmost column for this stack
X
X if *stackUp[n] <= last[n] then {
X #the stack just got smaller (or stayed the same)
X #blank out two rows for each card that has been removed
X row := lastRow[last[n]] #last row used by top card
X while *stackUp[n] < last[n] do {
X writeCursor (row-0, col); writes (blankLine)
X writeCursor (row-1, col); writes (blankLine)
X row -:= 2
X last[n] -:= 1 #count and update simultaneously
X }
X dieIf (*stackUp[n] ~= last[n], last[n])
X #re-write new top card
X if *stackUp[n] = 0 then
X if *stackDown[n] = 0 then
X writeBlank (2, col)
X else
X writeBack (2, col)
X else
X writeFront ([stackUp[n][-1]], firstRow[last[n]], col)
X } else {
X #the stack just got bigger -- display new cards
X s := stackUp[n][last[n]-(*stackUp[n]):0] #list of new cards
X writeFront (s, firstRow[last[n]+1], col)
X last[n] := *stackUp[n] #remember how much is displayed
X }
X
X writeCursor (2, (7 + col))
X writes (" 123456???"[1+*stackDown[n]]) #display the number of hidden cards
Xend #writeStack
X
X
X# w r i t e P i l e
X# Displays an image of the specified ace pile, face up (or blank if empty)
Xprocedure writePile (n)
Xstatic pileRow, pileCol
Xinitial {
X pileRow := [3,3,9,9]
X pileCol := [66,74,66,74]
X}
X if \invisible then return
X if 0 = pile[n] then writeBlank (pileRow[n], pileCol[n])
X else writeFront ([card(n,pile[n])], pileRow[n], pileCol[n])
Xend #writePile
X
X
X# w r i t e D e c k D o w n
X# Displays an image of deckDown (the face-down deck) in the proper spot.
Xprocedure writeDeckDown ()
X if \invisible then return
X if 0 < *deckDown then
X writeBack (21, 74)
X else
X writeBlank (21, 74)
X if (\isUNIX, getval("li") = 25, \getval("am")) then
X writeCursor (19, 76)
X else
X writeCursor (20, 76)
X writes (right(*deckDown, 2))
Xend #writeDeckDown
X
X
X# w r i t e D e c k U p
X# Displays an image of deckUp (the face-up deck) in the proper spot.
Xprocedure writeDeckUp ()
X if \invisible then return
X if 0 < *deckUp then
X writeFront ([deckUp[1]], 21, 66)
X else
X writeBlank (21, 66)
X if (\isUNIX, getval("li") = 25, \getval("am")) then
X writeCursor (19, 68)
X else
X writeCursor (20, 68)
X writes (right(*deckUp, 2))
Xend #writeDeckUp
X
X
X# w r i t e I n f o
X# Displays a new short string (up to 12 printing characters) in the
X# officially approved information area of the screen.
X# An empty string results in clearing the area and restoring normal attributes.
Xprocedure writeInfo (s)
SHAR_EOF
true || echo 'restore of kloncon.icn failed'
fi
echo 'End of part 2'
echo 'File kloncon.icn is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
From goer%sophist@gargoyle.uchicago.edu Sat Dec 8 03:52:25 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02517; Sat, 8 Dec 90 03:52:25 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Sat, 8 Dec 90 03:51 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA04506; Sat, 8 Dec 90 04:51:08 CST
Received: by sophist (4.1/UofC3.1X) id AA08425; Sat, 8 Dec 90 04:54:27 CST
Resent-Date: Sat, 8 Dec 90 03:51 MST
Date: Sat, 8 Dec 90 04:54:27 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike, part 03 of 05
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F2378841D133403C82@Arizona.edu>
Message-Id: <9012081054.AA08425@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is klondike.03 (part 3 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file kloncon.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping kloncon.icn'
else
echo 'x - continuing file kloncon.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'kloncon.icn' &&
X if \invisible then return
X writeCursor (16, 65)
X if \isDOS then
X writes (Vnormal, VclearEOL)
X else if \isUNIX then
X normal () & iputs (VclearEOL)
X if *s ~= 0 then writes (s)
Xend #writeInfo
X
X
X# c l i c k
X# Make a quick sound to accompany card transfers
Xprocedure click ()
Xlocal x
X if (\clicking) & (\isDOS) then {
X x := InPort (16r61)
X OutPort (16r61, 3)
X OutPort (16r61, x)
X }
Xend #click
X
X
X# g e t C m d C h a r
X# Returns an upper-case command character, echoed to current cursor position.
X# Fails if character wasn't "normal" and complaint was made.
X# For ESC, abort information is written, and ESC is returned.
X# Normal calling sequence (from within a command procedure) is thus:
X# until (s := getCmdChar ())
X# if s == ESC then fail
Xprocedure getCmdChar ()
Xlocal s
X s := getch () #get command character
X if s == "\0" then { #non-ASCII character
X getch () #discard keyboard scan code
X complain ()
X fail
X }
X s := map (s, &lcase, &ucase)
X if s == ESC then {
X if \isDOS then
X writeInfo (Vbold || "Cmd Aborted.")
X else if \isUNIX then
X writeInfo ("Cmd aborted.")
X }
X else
X writes (s) #echo the command character
X return s
Xend #getCmdChar
X
X
X# c o m p l a i n
X# Let the boob know he done something wrong
X# The short beep produced under isDOS is not as annoying as the normal beeeeep.
Xprocedure complain ()
Xlocal x
X if \isDOS then
X writeInfo (Vbold || "INVALID")
X else if \isUNIX then
X writeInfo ("INVALID")
X if \clicking then
X if \isDOS then {
X x := InPort (16r61)
X every 1 to 22 do
X OutPort (16r61, 3)
X OutPort (16r61, x)
X } else
X writes (Vbell)
Xend #complain
X
X
X# r e f r e s h S c r e e n
X# Re-write entire screen.
Xprocedure refreshScreen ()
X if \invisible then return
X initScreen ()
X every writeStack (-1 to -7 by -1)
X every writePile (1 to 4)
X writeDeckDown ()
X writeDeckUp ()
Xend #refreshScreen
SHAR_EOF
echo 'File kloncon.icn is complete' &&
true || echo 'restore of kloncon.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= klonsub.icn ==============
if test -f 'klonsub.icn' -a X"$1" != X"-c"; then
echo 'x - skipping klonsub.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting klonsub.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'klonsub.icn' &&
X############################################################################
X#
X# Name: klonsub.icn
X#
X# Title: subroutines for klondike
X#
X# Author: Norman H. Azadian
X#
X# Version: 1.2
X#
X############################################################################
X#
X# Links:
X#
X# See also: klondike.icn
X#
X############################################################################
X
X
X#klonsub.icn 901029 NHA
X#subroutines for Klondike
X
X# d i e I f
X# If the first argument succeeds, then write out the remaining args & die.
X# Note that the remaining arguments must succeed.
Xprocedure dieIf (failed, writeArgs[])
X every writes (&output, !writeArgs)
X write (&output)
X display ()
X every writes (&errout, !writeArgs)
X write (&errout)
X runerr (500)
Xend #dieIf
X
X
X# f i t O n S t a c k
X# Given a card and a stack number, fail unless card can be added to the stack.
X# Note that we disallow putting an Ace on a stack, period. This prevents
X# ever building a stack with 13 cards, which we can't display in 25 rows.
Xprocedure fitOnStack (c, n)
Xlocal top #top card on stack
X if *stackUp[n] = 0 then {
X dieIf (*stackDown[n] ~= 0, "Up empty, Down not")
X if c.rank ~= 13 then fail #only a king can go to empty stack
X } else {
X top := stackUp[n][-1] #copy of top card
X if (c.rank ~= (top.rank - 1)) then fail #wrong rank
X if (c.suit < 3) & (top.suit < 3) then fail #same color
X if (c.suit > 2) & (top.suit > 2) then fail #same color
X if c.rank = 1 then fail #no ace on stack
X dieIf (*stackUp[n] >= 12, "stack too big")
X }
X return #success
Xend #fitOnStack
X
X
X# c h e c k 4 a c e
X# Only has an effect when global automaticAce is set!
X# Given a stack number, check for an ace as the top of stackUp[n].
X# If present, move it over to it's ace pile, turn over the next card
X# from stackDown, and check again.
X# Must not be more than one up card in stack.
X# Returns a string of the operations performed.
Xprocedure check4ace (n)
Xlocal c, op
X op := ""
X if \automaticAce then {
X dieIf (1 < *stackUp[n])
X while 0 < *stackUp[n] do {
X c := stackUp[n][1] #copy of (top = bottom) up card
X if c.rank = 1 then { #it's an ace!
X pop (stackUp[n]) #remove it from the stack
X pile[c.suit] := 1 #move to ace pile
X op ||:= c.suit
X push (stackUp[n], get(stackDown[n])) #turn over card underneath
X writeStack (n)
X writePile (c.suit)
X click ()
X } else
X break #not an ace
X }
X }
X return op
Xend #check4ace
X
X
X# m o v e S t a c k
X# Move a stack to another stack, no questions asked.
X# Updates video and audio.
X# Returns any automatic ace operations that were done as a consequence.
X##It would be nice to do this in a visually and audibly more satisfying way
Xprocedure moveStack (src, dst)
X while put (stackUp[dst], get(stackUp[src]))
X put (stackUp[src], get(stackDown[src]))
X writeStack (src)
X writeStack (dst)
X click ()
X return check4ace (src)
Xend #moveStack
X
X
X# _ m o v e
X# This is the internal move, taking a operation string. No Thumbs allowed.
X# Upon success it returns the (possibly modified) operation string.
Xprocedure _move (op)
Xlocal src, dst, c, moved
X dieIf (op[1] ~== "M", "op is ", op)
X src := op[2]
X dst := op[3]
X moved := 0
X if src == "D" then {
X c := deckUp[1]
X if dst == "A" then { # Deck -> Ace
X if c.rank = (pile[c.suit] + 1) then {
X op[4] := c.suit # Deck -> Ace: fits - do it
X pile[c.suit] +:= 1
X writePile (c.suit)
X moved := 1
X } else
X fail # Deck -> Ace: doesn't fit
X } else { # Deck -> stack
X if fitOnStack (c, dst) then {
X put (stackUp[dst], c) # Deck -> stack: fits - do it
X writeStack (dst)
X moved := 1
X } else
X fail # Deck -> stack: doesn't fit
X }
X while moved ~= 0 do {
X pop (deckUp)
X writeDeckUp () # Deck -> somewhere, with success
X click ()
X moved := 0
X if \automaticAce then {
X if (c := deckUp[1]).rank = 1 then { #automatic Ace handling
X pile[c.suit] := 1
X op ||:= c.suit
X writePile (c.suit)
X moved := 1
X }
X }
X }
X } else {
X if dst == "A" then { # stack -> Ace
X c := stackUp[src][-1] #copy of card on top of stack
X if c.rank = (pile[c.suit] + 1) then {
X op[4] := c.suit # stack -> Ace: fits - do it
X pile[c.suit] +:= 1
X pull (stackUp[src])
X writeStack (src)
X click ()
X writePile (c.suit)
X if *stackUp[src] = 0 then {
X op[4] +:= 4 #mark this case for undo()
X put (stackUp[src], get(stackDown[src])) #turn over a card
X writeStack (src)
X click ()
X op ||:= check4ace (src)
X }
X } else {
X fail # stack -> Ace: doesn't fit
X }
X } else { # stack -> stack
X if fitOnStack (stackUp[src][1], dst) then {
X # stack -> stack: fits - do it
X op[4] := "123456789abcdef"[*stackUp[src]]
X op ||:= moveStack (src, dst)
X } else
X fail # stack -> stack: doesn't fit
X }
X }
X return op #success
Xend #move
X
X
X# t h u m b
X# Move to next spot in deckDown
X# Returns the operation performed (usually just "T3"), or fail if none possible.
Xprocedure thumb ()
Xlocal c, op, moved
X if *deckDown = *deckUp = 0 then
X return complain() #no cards left in the deck
X if *deckDown = 0 then
X while push (deckDown, pop(deckUp))
X op := "T" || if *deckDown < 3 then *deckDown else 3
X push (deckUp, pop(deckDown))
X push (deckUp, pop(deckDown))
X push (deckUp, pop(deckDown))
X writeDeckDown ()
X moved := 1
X while moved ~= 0 do {
X writeDeckUp ()
X click ()
X moved := 0
X if \automaticAce then {
X if deckUp[1].rank = 1 then {
X c := pop (deckUp)
X pile[c.suit] := 1
X op ||:= c.suit
X writePile (c.suit)
X moved := 1
X }
X }
X }
X return op
Xend #thumb
X
X
X# u n d o
X# backup one move, including any automatic ace moves
Xprocedure undo ()
Xlocal op, suit
X writes ("ndo")
X if op := pop (ops) then {
X writeInfo (op)
X # op looks like: Msdixxx
X # where x is an [optional] number 1..4 of an ace pile
X # and s is either a stack number or "D"
X # and d is either "A" or a number 1..7 of a stack
X # and i is an extra piece of info which may be valid
X case op[1] of {
X "M" : {
X dieIf ((*op < 4) | ((/automaticAce) & (4 < *op)), op)
X if op[2] == "D" then {
X #Move cards from Ace piles to deck, starting at end
X while 4 < *op do {
X suit := op[-1]
X pile[suit] := 0
X writePile (suit)
X push (deckUp, card(suit,1))
X writeDeckUp ()
X click ()
X op[-1] := ""
X }
X if op[3] == "A" then {
X # unMove Deck to Ace op[4]
X suit := op[4]
X push (deckUp, card(suit,pile[suit]))
X pile[suit] -:= 1
X writePile (suit)
X } else {
X # unMove Deck to stack op[3]
X push (deckUp, pull(stackUp[op[3]]))
X writeStack (op[3])
X }
X writeDeckUp ()
X } else {
X #Move cards from Ace piles to stack, starting at end
X while 4 < *op do {
X suit := op[-1]
X pile[suit] := 0
X writePile (suit)
X dieIf (1 < *stackUp[op[2]])
X push (stackDown[op[2]], pull(stackUp[op[2]]))
X push (stackUp[op[2]], card(suit,1))
X writeStack (op[2])
X click ()
X op[-1] := ""
X }
X if op[3] == "A" then {
X # unMove stack op[2] to Ace pile op[4]
X suit := op[4]
X if 4 < suit then {
X suit -:= 4 #ace pile card was last on stack
X dieIf (1 < *stackUp[op[2]])
X push (stackDown[op[2]], pull(stackUp[op[2]]))
X }
X put (stackUp[op[2]], card(suit,pile[suit]))
X pile[suit] -:= 1
X writePile (suit)
X writeStack (op[2])
X } else {
X # unMove top op[4] cards on stack op[2]
X # to stack op[3]
X dieIf (1 < *stackUp[op[2]])
X push (stackDown[op[2]], pull(stackUp[op[2]]))
X every 1 to ("16r" || op[4]) do
X push (stackUp[op[2]], pull(stackUp[op[3]]))
X writeStack (op[3])
X writeStack (-op[2])
X }
X }
X }
X "T" : {
X dieIf ((/automaticAce) & (*op ~= 2))
X ### op looks like: Tcxx
X ### where c is the number of cards thumbed (usually 3)
X ### and x is an optional number 1..4 of an ace pile
X ### There can be 0,1,2, or 3 of these x's.
X # move cards from Ace piles to deck, starting at end
X while 2 < *op do {
X suit := op[-1]
X pile[suit] := 0
X writePile (suit)
X push (deckUp, card(suit,1))
X writeDeckUp ()
X click ()
X op[-1] := ""
X }
X # then undo the Thumb operation itself
X dieIf (*deckUp = 0)
X every 1 to op[2] do
X push (deckDown, pop(deckUp))
X if *deckUp = 0 then
X while push (deckUp, pop(deckDown))
X writeDeckUp ()
X writeDeckDown ()
X }
X default : {
X if \isUNIX then reset_tty()
X stop ("Klondike: unknown operation `", op, "' in ops[]")
X }
X }
X click ()
X } else {
X ## Admittedly this is a bit of a kluge, but better than nothing ?
X if *deckDown = 0 then
X while push (deckDown, pop(deckUp))
X writeDeckUp ()
X writeDeckDown ()
X writeInfo ("Stack Empty")
X }
X
Xend #undo
X
X
X# s h o w L i s t
X# Display a list of cards at the current cursor position.
X# Intended for debugging only .
Xprocedure showList (lst)
Xlocal c
X every c := !lst do {
X if \isDOS then
X writes (color[c.suit], "A23456789TJQK"[c.rank], suitID[c.suit],
X Vnormal, " ")
X else if \isUNIX then {
X writes (color[c.suit], "A23456789TJQK"[c.rank], suitID[c.suit])
X normal (); writes(" ")
X }
X }
Xend #showList
X
X
X# c a r d 2 s t r
X# Given a list of card records, returns a string representation.
X# Even an empty list results in a non-zero string length.
Xprocedure card2str (lst)
Xlocal c, s
X s := "$"
X every c := !lst do
X s ||:= string(c.suit) || "123456789abcd"[c.rank]
X return s
Xend #card2str
X
X
X# s t r 2 c a r d
X# Given a string [as generated by card2str()],
X# return corresponding list of card records.
X# Fails if the string is invalid.
Xprocedure str2card (s)
Xlocal cc, i
X if s[i:=1] ~== "$" then fail
X cc := []
X while put (cc, card(s[i+:=1], integer("14r"||s[i+:=1])))
X return cc
Xend #str2card
X
X
X# s a v e S t a t e
X# Saves the current state in the named file, which is created/overwritten
X# as necessary.
X# Fails if the state was not successfully saved.
Xprocedure saveState (filename)
Xlocal f, i
X (f := open (filename, "c")) | fail
X write (f, &dateline)
X write (f, if \automaticAce then 1 else 0)
X write (f, if \clicking then 1 else 0)
X write (f, firstSeed)
X write (f, lastSeed)
X write (f, &random)
X every write (f, !pile)
X every write (f, card2str(!stackUp))
X every write (f, card2str(!stackDown))
X write (f, card2str(deckUp))
X write (f, card2str(deckDown))
X write (f, totalGames)
X write (f, totalAces)
X every write (f, !ops)
X return close (f)
Xend #saveState
X
X
X# r e s t o r e S t a t e
X# Restore game from the named file.
X# Fails if the file isn't there, isn't readable, or isn't correct format.
X# Otherwise returns date the file was last written.
X# Note that we do not update the screen here !!
Xprocedure restoreState (filename)
Xlocal f, date
X if not (f := open (filename, "r")) then fail
X if (not (date := read(f))) | (*date = 0) then fail
X automaticAce := if read (f) == "0" then &null else 1
X clicking := if read (f) == "0" then &null else 1
X firstSeed := read (f)
X lastSeed := read (f)
X &random := read (f)
X every ((!pile) := read(f))
X every ((!stackUp) := str2card (read(f)))
X every ((!stackDown) := str2card (read(f)))
X deckUp := str2card (read(f))
X deckDown := str2card (read(f))
X totalGames := read (f)
X totalAces := read (f)
X ops := []
X while push (ops, read (f))
X dieIf (not close (f), "can't close")
X return date
Xend #restoreState
X
X
X# n e w G a m e
X# Set up all the global variables for a new game.
X# Returns the seed used to generate this game.
Xprocedure newGame ()
Xlocal i, j, s, seed
X initScreen ()
X
X #initialize deck, stacks, piles
X ops := [] #no operations done yet
X deckUp := [] #deck in hand, face-up
X deckDown := [] #deck in hand, face-down
X stackUp := list(7, 0) #columns on table, face up
X stackDown := list(7, 0) #columns on table, face down
X pile := list(4, 0) #aces - only top rank stored
X every i := 1 to 4 do
X every j := 1 to 13 do
X put (deckDown, card(i, j)) #take cards out of the box
X
X seed := &random
X if not \invisible then { #Vblink not defined in Batch mode
X if \isDOS then
X writeInfo (Vblink || "Shuffling")
X else if \isUNIX then
X writeInfo ("Shuffling")
X }
X every 1 to 100 do
X ?deckDown :=: ?deckDown
X writeInfo ("")
X
X every !stackUp := []
X every !stackDown := []
X every i := 1 to 7 do {
X push (stackUp[i], get(deckDown))
X writeStack (-i)
X click ()
X every j := (i+1) to 7 do {
X push (stackDown[j], get(deckDown))
X writeStack (-j)
X click ()
X }
X### writeStack (-i) ### this replaces 2 calls above
X }
X writeDeckDown()
X
X #handle any Aces which are showing
X every i := 1 to 7 do
X if *(s := check4ace (i)) ~= 0 then
X push (ops, "M" || string(i) || "A" || string(integer(s) + 4))
X return seed
Xend #newGame
SHAR_EOF
true || echo 'restore of klonsub.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= itlib.icn ==============
if test -f 'itlib.icn' -a X"$1" != X"-c"; then
echo 'x - skipping itlib.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting itlib.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'itlib.icn' &&
X########################################################################
SHAR_EOF
true || echo 'restore of itlib.icn failed'
fi
echo 'End of part 3'
echo 'File itlib.icn is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
From goer%sophist@gargoyle.uchicago.edu Sat Dec 8 03:53:06 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02536; Sat, 8 Dec 90 03:53:06 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Sat, 8 Dec 90 03:51 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA04509; Sat, 8 Dec 90 04:51:37 CST
Received: by sophist (4.1/UofC3.1X) id AA08433; Sat, 8 Dec 90 04:54:56 CST
Resent-Date: Sat, 8 Dec 90 03:52 MST
Date: Sat, 8 Dec 90 04:54:56 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike, part 04 of 05
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F2376F204103403C03@Arizona.edu>
Message-Id: <9012081054.AA08433@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is klondike.04 (part 4 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file itlib.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 4; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping itlib.icn'
else
echo 'x - continuing file itlib.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'itlib.icn' &&
X#
X# Name: itlib.icn
X#
X# Title: Icon termlib-type tools
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.23
X#
X#########################################################################
X#
X# I place this and future versions of itlib in the public domain - RLG
X#
X#########################################################################
X#
X# The following library represents a series of rough functional
X# equivalents to the standard Unix low-level termcap routines. They
X# are not meant as exact termlib clones. Nor are they enhanced to
X# take care of magic cookie terminals, terminals that use \D in their
X# termcap entries, or, in short, anything I felt would not affect my
X# normal, day-to-day work with ANSI and vt100 terminals.
X#
X# Requires: A unix platform & co-expressions. There is an MS-DOS
X# version, itlibdos.icn.
X#
X# setname(term)
X# Use only if you wish to initialize itermlib for a terminal
X# other than what your current environment specifies. "Term" is the
X# name of the termcap entry to use. Normally this initialization is
X# done automatically, and need not concern the user.
X#
X# getval(id)
X# Works something like tgetnum, tgetflag, and tgetstr. In the
X# spirit of Icon, all three have been collapsed into one routine.
X# Integer valued caps are returned as integers, strings as strings,
X# and flags as records (if a flag is set, then type(flag) will return
X# "true"). Absence of a given capability is signalled by procedure
X# failure.
X#
X# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
X# Analogous to tgoto. "Cm" is the cursor movement command for
X# the current terminal, as obtained via getval("cm"). Igoto()
X# returns a string which, when output via iputs, will cause the
X# cursor to move to column "destcol" and line "destline." Column and
X# line are always calculated using a *one* offset. This is far more
X# Iconish than the normal zero offset used by tgoto. If you want to
X# go to the first square on your screen, then include in your program
X# "iputs(igoto(getval("cm"),1,1))."
X#
X# iputs(cp,affcnt)
X# Equivalent to tputs. "Cp" is a string obtained via getval(),
X# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
X# count of affected lines. It is only relevant for terminals which
X# specify proportional (starred) delays in their termcap entries.
X#
X# Bugs: I have not tested these routines on terminals that require
X# padding. These routines WILL NOT WORK if your machines stty com-
X# mand has no -g option (tisk, tisk). This includes NeXT worksta-
X# tions, and some others that I haven't had time to pinpoint.
X#
X##########################################################################
X#
X# Requires: UNIX, co-expressions
X#
X# See also: iscreen.icn (a set of companion utilities)
X#
X##########################################################################
X
X
Xglobal tc_table, tty_speed
Xrecord true()
X
X
Xprocedure check_features()
X
X local in_params, line
X # global tty_speed
X
X initial {
X find("unix",map(&features)) |
X er("check_features","unix system required",1)
X find("o-expres",&features) |
X er("check_features","co-expressions not implemented - &$#!",1)
X system("/bin/stty tabs") |
X er("check_features","can't set tabs option",1)
X }
X
X # clumsy, clumsy, clumsy, and probably won't work on all systems
X tty_speed := getspeed()
X return "term characteristics reset; features check out"
X
Xend
X
X
X
Xprocedure setname(name)
X
X # Sets current terminal type to "name" and builds a new termcap
X # capability database (residing in tc_table). Fails if unable to
X # find a termcap entry for terminal type "name." If you want it
X # to terminate with an error message under these circumstances,
X # comment out "| fail" below, and uncomment the er() line.
X
X #tc_table is global
X
X check_features()
X
X tc_table := table()
X tc_table := maketc_table(getentry(name)) | fail
X # er("setname","no termcap entry found for "||name,3)
X return "successfully reset for terminal " || name
X
Xend
X
X
X
Xprocedure getname()
X
X # Getname() first checks to be sure we're running under Unix, and,
X # if so, tries to figure out what the current terminal type is,
X # checking successively the value of the environment variable
X # TERM, and then the output of "tset -". Terminates with an error
X # message if the terminal type cannot be ascertained.
X
X local term, tset_output
X
X check_features()
X
X if not (term := getenv("TERM")) then {
X tset_output := open("/bin/tset -","pr") |
X er("getname","can't find tset command",1)
X term := !tset_output
X close(tset_output)
X }
X return \term |
X er("getname","can't seem to determine your terminal type",1)
X
Xend
X
X
X
Xprocedure er(func,msg,errnum)
X
X # short error processing utility
X write(&errout,func,": ",msg)
X exit(errnum)
X
Xend
X
X
X
Xprocedure getentry(name, termcap_string)
X
X # "Name" designates the current terminal type. Getentry() scans
X # the current environment for the variable TERMCAP. If the
X # TERMCAP string represents a termcap entry for a terminal of type
X # "name," then getentry() returns the TERMCAP string. Otherwise,
X # getentry() will check to see if TERMCAP is a file name. If so,
X # getentry() will scan that file for an entry corresponding to
X # "name." If the TERMCAP string does not designate a filename,
X # getentry() will scan /etc/termcap for the correct entry.
X # Whatever the input file, if an entry for terminal "name" is
X # found, getentry() returns that entry. Otherwise, getentry()
X # fails.
X
X local f, getline, line, nm, ent1, ent2
X
X # You can force getentry() to use a specific termcap file by cal-
X # ling it with a second argument - the name of the termcap file
X # to use instead of the regular one, or the one specified in the
X # termcap environment variable.
X /termcap_string := getenv("TERMCAP")
X
X if \termcap_string ? (not match("/"), pos(0) | tab(find("|")+1), =name)
X then return termcap_string
X else {
X
X # The logic here probably isn't clear. The idea is to try to use
X # the termcap environment variable successively as 1) a termcap en-
X # try and then 2) as a termcap file. If neither works, 3) go to
X # the /etc/termcap file. The else clause here does 2 and, if ne-
X # cessary, 3. The "\termcap_string ? (not match..." expression
X # handles 1.
X
X if find("/",\termcap_string)
X then f := open(termcap_string)
X /f := open("/etc/termcap") |
X er("getentry","I can't access your /etc/termcap file",1)
X
X getline := create read_file(f)
X
X while line := @getline do {
X if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
X entry := ""
X while (\line | @getline) ? {
X if entry ||:= 1(tab(find(":")+1), pos(0))
X then {
X close(f)
X # if entry ends in tc= then add in the named tc entry
X entry ?:= tab(find("tc=")) ||
X # recursively fetch the new termcap entry
X (move(3), getentry(tab(find(":"))) ?
X # remove the name field from the new entry
X (tab(find(":")+1), tab(0)))
X return entry
X }
X else {
X \line := &null # must precede the next line
X entry ||:= trim(trim(tab(0),'\\'),':')
X }
X }
X }
X }
X }
X
X close(f)
X er("getentry","can't find and/or process your termcap entry",3)
X
Xend
X
X
X
Xprocedure read_file(f)
X
X # Suspends all non #-initial lines in the file f.
X # Removes leading tabs and spaces from lines before suspending
X # them.
X
X local line
X
X \f | er("read_tcap_file","no valid termcap file found",3)
X while line := read(f) do {
X match("#",line) & next
X line ?:= (tab(many('\t ')) | &null, tab(0))
X suspend line
X }
X
X fail
X
Xend
X
X
X
Xprocedure maketc_table(entry)
X
X # Maketc_table(s) (where s is a valid termcap entry for some
X # terminal-type): Returns a table in which the keys are termcap
X # capability designators, and the values are the entries in
X # "entry" for those designators.
X
X local k, v
X
X /entry & er("maketc_table","no entry given",8)
X if entry[-1] ~== ":" then entry ||:= ":"
X
X /tc_table := table()
X
X entry ? {
X
X tab(find(":")+1) # tab past initial (name) field
X
X while tab((find(":")+1) \ 1) ? {
X &subject == "" & next
X if k := 1(move(2), ="=")
X then tc_table[k] := Decode(tab(find(":")))
X else if k := 1(move(2), ="#")
X then tc_table[k] := integer(tab(find(":")))
X else if k := 1(tab(find(":")), pos(-1))
X then tc_table[k] := true()
X else er("maketc_table", "your termcap file has a bad entry",3)
X }
X }
X
X return tc_table
X
Xend
X
X
X
Xprocedure getval(id)
X
X /tc_table := maketc_table(getentry(getname())) |
X er("getval","can't make a table for your terminal",4)
X
X return \tc_table[id] | fail
X # er("getval","the current terminal doesn't support "||id,7)
X
Xend
X
X
X
Xprocedure Decode(s)
X
X # Does things like turn ^ plus a letter into a genuine control
X # character.
X
X new_s := ""
X
X s ? {
X
X while new_s ||:= tab(upto('\\^')) do {
X chr := move(1)
X if chr == "\\" then {
X new_s ||:= {
X case chr2 := move(1) of {
X "\\" : "\\"
X "^" : "^"
X "E" : "\e"
X "b" : "\b"
X "f" : "\f"
X "n" : "\n"
X "r" : "\r"
X "t" : "\t"
X default : {
X if any(&digits,chr2) then {
X char(integer("8r"||chr2||move(2 to 0 by -1))) |
X er("Decode","bad termcap entry",3)
X }
X else chr2
X }
X }
X }
X }
X else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
X }
X new_s ||:= tab(0)
X }
X
X return new_s
X
Xend
X
X
X
Xprocedure igoto(cm,col,line)
X
X local colline, range, increment, str, outstr, chr, x, y
X
X if col > (tc_table["co"]) | line > (tc_table["li"]) then {
X colline := string(\col) || "," || string(\line) | string(\col|line)
X range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
X er("igoto",colline || " out of range " || (\range|""),9)
X }
X
X # Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
X increment := -1
X outstr := ""
X
X cm ? {
X while outstr ||:= tab(find("%")) do {
X tab(match("%"))
X chr := move(1)
X if case chr of {
X "." : outstr ||:= char(line + increment)
X "+" : outstr ||:= char(line + ord(move(1)) + increment)
X "d" : {
X str := string(line + increment)
X outstr ||:= right(str, integer(tab(any('23'))), "0") | str
X }
X }
X then line :=: col
X else {
X case chr of {
X "n" : line := ixor(line,96) & col := ixor(col,96)
X "i" : increment := 0
X "r" : line :=: col
X "%" : outstr ||:= "%"
X "B" : line := ior(ishift(line / 10, 4), line % 10)
X ">" : {
X x := move(1); y := move(1)
X line > ord(x) & line +:= ord(y)
X &null
X }
X } | er("goto","bad termcap entry",5)
X }
X }
X return outstr || tab(0)
X }
X
Xend
X
X
X
Xprocedure iputs(cp, affcnt)
X
X local baud_rates, char_rates, i, delay, PC
X static num_chars, char_times
X # global tty_speed
X
X initial {
X num_chars := &digits ++ '.'
X char_times := table()
X # Baud rates in decimal, not octal (as in termio.h)
X baud_rates := [0,7,8,9,10,11,12,13,14,15]
X char_rates := [0,333,166,83,55,41,20,10,10,10]
X every i := 1 to *baud_rates do {
X char_times[baud_rates[i]] := char_rates[i]
X }
X }
X
X type(cp) == "string" |
X er("iputs","you can't iputs() a non-string value!",10)
X
X cp ? {
X delay := tab(many(num_chars))
X if ="*" then {
X delay *:= \affcnt |
X er("iputs","affected line count missing",6)
X }
X writes(tab(0))
X }
X
X if (\delay, tty_speed ~= 0) then {
X PC := tc_table["pc"] | "\000"
X char_time := char_times[tty_speed] | (return "speed error")
X delay := (delay * char_time) + (char_time / 2)
X every 1 to delay by 10
X do writes(PC)
X }
X
X return
X
Xend
X
X
X
Xprocedure getspeed()
X
X local stty_g, stty_output, c_cflag, o_speed
X
X stty_g := open("/bin/stty -g 2>&1","pr") |
X er("getspeed","Can't access your stty command.",4)
X stty_output := !stty_g
X close(stty_g)
X
X \stty_output ? {
X # tab to the third field of the output of the stty -g cmd
X tab(find(":")+1) & tab(find(":")+1) &
X c_cflag := integer("16r"||tab(find(":")))
X } | er("getspeed","Unable to unwind your stty -g output.",4)
X
X o_speed := iand(15,c_cflag)
X return o_speed
X
Xend
SHAR_EOF
echo 'File itlib.icn is complete' &&
true || echo 'restore of itlib.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= getchlib.icn ==============
if test -f 'getchlib.icn' -a X"$1" != X"-c"; then
echo 'x - skipping getchlib.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting getchlib.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'getchlib.icn' &&
X############################################################################
X#
X# Name: getchlib.icn
X#
X# Title: Implementation of getch() for Unix (and more)
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.11
X#
X############################################################################
X#
X# I place this and future versions of getchlib in the public domain - RLG
X#
X############################################################################
X#
X# Implementing getch() is a much, much more complex affair under Unix
X# than it is under, say, MS-DOS. This library represents one,
X# solution to the problem - one which can be run as a library, and
X# need not be compiled into the run-time system.
X#
X# Four basic utilities are included here:
X#
X# getch() - waits until a keystroke is available &
X# returns it without displaying it on the screen
X# getche() - same as getch() only with echo
X# getse(s) - like getche() only for strings. The optional
X# argument s gives getse() something to start with. Use this
X# if, say, you want to read single characters in cbreak mode,
X# but get more input if the character read is the first part
X# of a longer command. If the user backspaces over everything
X# that has been input, getse() fails. Returns on \r or \n.
X# reset_tty() - absolutely vital routine for putting the cur-
X# rent tty line back into cooked mode; call it before exiting
X# or you will find yourself with a locked-up terminal; use it
X# also if you must temporarily restore the terminal to cooked
X# mode
X#
X# Note that getse() *must* be used in place of read(&input) if you
X# are planning on using getch() or getche(), since read(&input)
X# assumes a tty with "sane" settings.
X#
X# Warning: The routines below do not do any sophisticated output
X# processing. As noted above, they also put your tty line in raw
X# mode. I know, I know: "Raw is overkill - use cbreak." But in
X# a world that includes SysV, one must pick a lowest common denomi-
X# nator. And no, icanon != cbreak.
X#
X# Bugs: These routines will not work on systems that do not imple-
X# ment the -g option for the stty command. The NeXT workstation is
X# an example of such a system. Tisk, tisk.
X#
X############################################################################
X#
X# Example program:
X#
X# The following program is a simple file viewer. To run, it
X# needs to be linked with itlib.icn, iscreen.icn, and this file
X# (getchlib.icn).
X#
X# procedure main(a)
X#
X# # Simple pager/file searcher for Unix systems. Must be linked
X# # with itlib.icn and iscreen.icn.
X#
X# local intext, c, s
X#
X# # Open input file
X# intext := open(a[1],"r") | {
X# write(&errout,"Can't open input file.")
X# exit(1)
X# }
X#
X# # Initialize screen
X# clear()
X# print_screen(intext) | exit(0)
X#
X# # Prompt & read input
X# repeat {
X# iputs(igoto(getval("cm"), 1, getval("li")))
X# emphasize()
X# writes("More? (y/n or /search):")
X# write_ce(" ")
X# case c := getche() of {
X# "y" : print_screen(intext) | break
X# " " : print_screen(intext) | break
X# "n" : break
X# "q" : break
X# "/" : {
X# iputs(igoto(getval("cm"), 1, getval("li")))
X# emphasize()
X# writes("Enter search string:")
X# write_ce(" ")
X# pattern := GetMoreInput()
X# /pattern | "" == pattern & next
X# # For more complex patterns, use findre() (IPL findre.icn)
X# if not find(pattern, s := !intext) then {
X# iputs(igoto(getval("cm"), 1, getval("li")))
X# emphasize()
X# write_ce("String not found.")
X# break
X# }
X# else print_screen(intext, s) | break
X# }
X# }
X# }
X#
X# reset_tty()
X# write()
X# exit(0)
X#
X# end
X#
X# procedure GetMoreInput(c)
X#
X# local input_string
X# static BS
X# initial BS := getval("bc") | "\b"
X#
X# /c := ""
X# if any('\n\r', chr := getch())
X# then return c
X# else {
X# chr == BS & fail
X# writes(chr)
X# input_string := getse(c || chr) | fail
X# if any('\n\r', input_string)
X# then fail else (return input_string)
X# }
X#
X# end
X#
X# procedure print_screen(f,s)
X#
X# if /s then
X# begin := 1
X# # Print top line, if one is supplied
X# else {
X# iputs(igoto(getval("cm"), 1, 1))
X# write_ce(s ? tab(getval("co") | 0))
X# begin := 2
X# }
X#
X# # Fill the screen with lines from f; clear and fail on EOF.
X# every i := begin to getval("li") - 1 do {
X# iputs(igoto(getval("cm"), 1, i))
X# if not write_ce(read(f) ? tab(getval("co") | 0)) then {
X# # Clear remaining lines on the screen.
X# every j := i to getval("li") do {
X# iputs(igoto(getval("cm"), 1, j))
X# iputs(getval("ce"))
X# }
X# iputs(igoto(getval("cm"), 1, i))
X# fail
X# }
X# }
X# return
X#
X# end
X#
X# procedure write_ce(s)
X#
X# normal()
X# iputs(getval("ce")) |
X# writes(repl(" ",getval("co") - *s))
X# writes(s)
X# return
X#
X# end
X#
X############################################################################
X#
X# Requires: UNIX
X#
X# Links: itlib.icn
X#
X############################################################################
X
X
Xglobal c_cc, current_mode # what mode are we in, raw or cooked?
Xrecord termio_struct(vintr,vquit,verase,vkill)
X
Xprocedure getse(s)
X
X # getse() - like getche, only for strings instead of single chars
X #
X # This procedure *must* be used instead of read(&input) if getch
X # and/or getche are to be used, since these put the current tty
X # line in raw mode.
X #
X # Note that the buffer can be initialized by calling getse with a
X # string argument. Note also that, as getse now stands, it will
X # fail if the user backspaces over everything that has been input.
X # This change does not coincide with its behavior in previous ver-
X # sions. It can be changed by commenting out the line "if *s < 1
SHAR_EOF
true || echo 'restore of getchlib.icn failed'
fi
echo 'End of part 4'
echo 'File getchlib.icn is continued in part 5'
echo 5 > _shar_seq_.tmp
exit 0
From goer%sophist@gargoyle.uchicago.edu Sat Dec 8 03:53:23 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02554; Sat, 8 Dec 90 03:53:23 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Sat, 8 Dec 90 03:52 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA04514; Sat, 8 Dec 90 04:52:01 CST
Received: by sophist (4.1/UofC3.1X) id AA08441; Sat, 8 Dec 90 04:55:20 CST
Resent-Date: Sat, 8 Dec 90 03:52 MST
Date: Sat, 8 Dec 90 04:55:20 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: klondike, part 05 of 05
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F23763851003403005@Arizona.edu>
Message-Id: <9012081055.AA08441@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is klondike.05 (part 5 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file getchlib.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 5; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping getchlib.icn'
else
echo 'x - continuing file getchlib.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'getchlib.icn' &&
X # then fail" below, and uncommenting the line "if *s < 1 then
X # next."
X
X local chr
X static BS
X initial {
X BS := getval("bc") | "\b"
X if not getval("bs") then {
X reset_tty()
X stop("Your terminal can't backspace!")
X }
X }
X
X /s := ""
X repeat {
X case chr := getch() | fail of {
X "\r"|"\n" : return s
X c_cc.vkill : {
X if *s < 1 then next
X every 1 to *s do writes(BS)
X s := ""
X }
X c_cc.verase : {
X # if *s < 1 then next
X writes(BS) & s := s[1:-1]
X if *s < 1 then fail
X }
X default: writes(chr) & s ||:= chr
X }
X }
X
Xend
X
X
X
Xprocedure setup_tty()
X change_tty_mode("setup")
X return
Xend
X
X
X
Xprocedure reset_tty()
X
X # Reset (global) mode switch to &null to show we're in cooked mode.
X current_mode := &null
X change_tty_mode("reset")
X return
X
Xend
X
X
X
Xprocedure getch()
X
X local chr
X
X # If the global variable current_mode is null, then we have to
X # reset the terminal to raw mode.
X if /current_mode := 1 then
X setup_tty()
X
X chr := reads(&input)
X case chr of {
X c_cc.vintr : reset_tty() & stop() # shouldn't hard code this in
X c_cc.vquit : reset_tty() & stop()
X default : return chr
X }
X
Xend
X
X
X
Xprocedure getche()
X
X local chr
X
X # If the global variable current_mode is null, then we have to
X # reset the terminal to raw mode.
X if /current_mode := 1 then
X setup_tty()
X
X chr := reads(&input)
X case chr of {
X c_cc.vintr : reset_tty() & stop()
X c_cc.vquit : reset_tty() & stop()
X default : writes(chr) & return chr
X }
X
Xend
X
X
X
Xprocedure change_tty_mode(switch)
X
X # global c_cc (global record containing values for kill, etc. chars)
X local get_term_params, i
X static reset_string
X initial {
X getval("li") # check to be sure itlib is set up
X find("unix",map(&features)) |
X stop("change_tty_mode: These routines must run under Unix.")
X get_term_params := open("/bin/stty -g 2>&1","pr")
X reset_string := !get_term_params
X close(get_term_params)
X reset_string ? {
X # tab upto the fifth field of the output of the stty -g cmd
X # fields of stty -g seem to be the same as those of the
X # termio struct, except that the c_line field is missing
X every 1 to 4 do tab(find(":")+1)
X c_cc := termio_struct("\x03","\x1C","\x08","\x15")
X every i := 1 to 3 do {
X c_cc[i] := char(integer("16r"||tab(find(":"))))
X move(1)
X }
X c_cc[i+1] := char(integer("16r"||tab(0)))
X }
X }
X
X if switch == "setup"
X then system("/bin/stty -echo raw")
X else system("/bin/stty "||reset_string)
X
X return
X
Xend
SHAR_EOF
echo 'File getchlib.icn is complete' &&
true || echo 'restore of getchlib.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= iscreen.icn ==============
if test -f 'iscreen.icn' -a X"$1" != X"-c"; then
echo 'x - skipping iscreen.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting iscreen.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'iscreen.icn' &&
X############################################################################
X#
X# Name: iscreen.icn
X#
X# Title: Icon screen functions
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.12
X#
X############################################################################
X#
X# This and future version of iscreen are placed in the public domain - RLG
X#
X############################################################################
X#
X# This file contains some rudimentary screen functions for use with
X# itlib.icn (termlib-like routines for Icon).
X#
X# clear() - clears the screen (tries several methods)
X# emphasize() - initiates emphasized mode
X# normal(mode) - resets to normal mode; if mode is null,
X# or "b," normal() assumes you were in emphasize mode,
X# otherwise you are assumed to have been in underline mode
X# message(s) - displays message s on 2nd-to-last line
X# underline() - initiates underline mode
X# status_line(s,s2,p) - draws status line s on the 3rd-to-last
X# screen line; if s is too short for the terminal, s2 is used;
X# if p is nonnull then it either centers, left-, or right-justi-
X# fies, depending on the value, "c," "l," or "r."
X#
X############################################################################
X#
X# Requires: UNIX
X#
X# Links: itlib.icn (or your OS-specific port of itlib)
X#
X# See also: boldface.icn
X#
X############################################################################
X
X
Xprocedure clear()
X
X # Clears the screen. Tries several methods.
X
X if not iputs(getval("cl"))
X then iputs(igoto(getval("cm"),1,1))
X if not iputs(getval("cd"))
X then {
X every i := 1 to getval("li") do {
X iputs(igoto(getval("cm"),1,i))
X iputs(getval("ce"))
X }
X iputs(igoto(getval("cm"),1,1))
X }
X return
X
Xend
X
X
X
Xprocedure emphasize()
X
X static bold_str, cookie_str
X initial {
X if bold_str := getval("so")
X then cookie_str := repl(getval("bc") | "\b", getval("sg"))
X else {
X if bold_str := getval("us")
X then cookie_str := repl(getval("bc") | "\b", getval("ug"))
X }
X }
X
X iputs(\bold_str)
X iputs(\cookie_str)
X return
X
Xend
X
X
X
Xprocedure underline()
X
X static underline_str, cookie_str
X initial {
X if underline_str := getval("us")
X then cookie_str := repl(getval("bc") | "\b", getval("sg"))
X }
X
X iputs(\underline_str)
X iputs(\cookie_str)
X return
X
Xend
X
X
X
Xprocedure normal(mode)
X
X static UN_bold_str, bold_cookie_str,
X UN_underline_str, underline_cookie_str
X initial {
X
X if UN_bold_str := getval("se") then
X bold_cookie_str := repl(getval("bc") | "\b", getval("sg"))
X else {
X UN_bold_str := getval("ue")
X bold_cookie_str := repl(getval("bc")|"\b", getval("ug"))
X }
X if UN_underline_str := getval("ue") then
X underline_cookie_str := repl(getval("bc")|"\b", getval("ug"))
X }
X
X if /mode | (mode == "b") then {
X iputs(\UN_bold_str)
X iputs(\bold_cookie_str)
X return
X }
X
X iputs(\UN_underline_str)
X iputs(\underline_cookie_str)
X return
X
Xend
X
X
X
Xprocedure status_line(s,s2,p)
X
X # Writes a status line on the terminal's third-to-last line
X # The only necessary argument is s. S2 (optional) is used
X # for extra narrow screens. In other words, by specifying
X # s2 you give status_line an alternate, shorter status string
X # to display, in case the terminal isn't wide enough to sup-
X # port s. If p is nonnull, then the status line is either
X # centered (if equal to "c"), left justified ("l"), or right
X # justified ("r").
X
X local width
X
X /s := ""
X width := getval("co")
X if *s > width then {
X (*s2 < width, s := \s2) |
X er("status_line","Your terminal is too narrow.",4)
X }
X case \p of {
X "c" : s := center(s,width-1)
X "l" : s := left(s,width-1)
X "r" : s := right(s,width-1)
X default: stop("status_line: Unknown option "||string(p),4)
X }
X
X iputs(igoto(getval("cm"), 1, getval("li")-2))
X emphasize(); writes(s); iputs(getval("ce"))
X normal()
X return
X
Xend
X
X
X
Xprocedure message(s)
X
X # Display prompt s on the second-to-last line of the screen.
X # I hate to use the last line, due to all the problems with
X # automatic scrolling.
X
X /s := ""
X normal()
X iputs(igoto(getval("cm"), 1, getval("li")-1))
X writes(s[1:getval("co")] | s)
X iputs(getval("ce"))
X return
X
Xend
SHAR_EOF
true || echo 'restore of iscreen.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= klondike.man ==============
if test -f 'klondike.man' -a X"$1" != X"-c"; then
echo 'x - skipping klondike.man (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting klondike.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'klondike.man' &&
X
X
X - 1 -
X
X
XKLONDIKE(6) KLONDIKE(6)
X
X
X
X NAME
X klondike -- one of the many versions of solitaire
X
X SYNOPSIS
X klondike -[ACD] [-B gameCount] [-R randomSeed]
X
X DESCRIPTION
X This is actually a popular variation on the Klondike version of
X Solitaire (or Patience) as described on page 181 of my 1963
X version of "Hoyle's Rules of Games". The difference is that
X here we go through the deck (stock) 3 cards at a time instead
X of one-by-one, and we allow it any number of times.
X
X It should run on any ANSI-compatible terminal, but it looks
X best on a PC, preferably color.
X
X OPTIONS
X Options may be either upper or lower case. They may be given
X in any order. Parameters follow their options with whitespace
X inbetween. Each option must be given as a separate argument.
X
X -A disables automatically putting uncovered Ace cards
X on the appropriate pile. Note that, in any case, it is
X not allowed to put an Ace onto a stack, as this could lead
X to building stacks which are too big to display with 25 lines.
X
X -B count
X Batch mode. The requested number of games is played and
X the average number of cards promoted to the ace piles is
X written to the standard output. No other I/O is performed.
X
X -C disable the "click" for silent games
X
X -D enable special debugging commands which, among other things,
X allow one to cheat
X
X -R seed
X set the random seed to the designated value
X
X COMMANDS
X H or ? display a Help screen
X
X ^L (control-L) redraws the screen
X
X A Automatic mode. Plays the game until nothing useful
X remains to be done, or until any key is struck.
X
X B Boss key. The screen is blanked and the current position
X is saved. When the game is started again in the usual
X way, this saved game will be automatically restored and
X the save file deleted.
X
X C Continuous mode. The computer plays games automatically
X until a key is struck. Two statistics are displayed:
X the number of games already played, and the total number
X of aces which have been promoted to the ace piles.
X
X M Move a card from the deck or a stack to a stack or an
X ace pile.
X
X Q Quit this game, with the opportunity to play another.
X
X S Suggest a possible move. Hitting this key multiple times
X results in multiple suggestions being displayed. When
X there is nothing interesting left to do, it will suggest
X "Thumb".
X
X T Thumb. Remove the top 3 cards from the face-down deck
X and lay them face-up on the face-up deck.
X
X U Undo. This can be used all the way back to the start
X of the current game.
X
X Z Debug. This is only enabled when the -D option has
X been given on the command line. There is a sub-menu
X of commands available, including a (very brief) Help
X summary.
X
X The Move command takes two parameters: source and destination.
X Possible sources are: D for the Deck of face-up cards; and a
X number from 1 to 7 inclusive, meaning the corresponding stack.
X Possible destinations are the stacks (1-7) and A for the
X appropriate ace pile. For instance, to move the visible card
X from the face-up deck to stack 4, one types the three characters:
X "MD4". Actually, the "M" character itself is optional, which
X explains why the "debug" command isn't invoked with a "D".
X
X BUGS
X Slow.
X Doesn't use termcap for maximum portability.
X The program's play is simplistic, with no concept of strategy.
X
X
X FILES
X klondike.sav Position is checkpointed here when the Boss key is used.
X klondike.sv? Position checkpointed here with the "S" debug command.
X "?" can be any (upper-case) character legal in your
X filesystem.
X
X ACKNOWLEDGEMENT
X The inspiration, name, and user interface were lifted
X wholesale from a game copyrighted in 1985 by Allyn Wade.
X
X VERSION
X 1.41 -- 26 November, 1990
X
X AUTHOR
X Norman H. Azadian
X naz@hslrswi
X
SHAR_EOF
true || echo 'restore of klondike.man failed'
rm -f _shar_wnt_.tmp
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XThis package is the Unix port of Norman H. Azadian's DOS klondike
Xprogram. To test, just mv Makefile.dist to Makefile, and make.
XTo install, su root, and then make install. Needs a 25-line term
Xwith at least 80 cols. WILL NOT WORK ON SYSTEMS THAT DO NOT IM-
XPLEMENT THE STTY -G OPTION (TSK, TSK). UNLESS YOU LIKE HAVING A
XLOCKED UP KEYBOARD, DON'T EVEN THINK OF TRYING KLONDIKE ON SUCH A
XSYSTEM.
X
XIt's a nice card game, but a pretty rough hack for Unix.
X
X-Richard Goerwitz
SHAR_EOF
true || echo 'restore of README failed'
rm -f _shar_wnt_.tmp
fi
# ============= Makefile.dist ==============
if test -f 'Makefile.dist' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile.dist (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Makefile.dist (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.dist' &&
XPROGNAME = klondike
X
X# Please edit these to reflect your local file structure & conventions.
XDESTDIR = /usr/local/bin
XOWNER = bin
XGROUP = bin
X
XMAN = klondike.man
XSRC = klondike.icn kloncon.icn klonsub.icn
XLIB = itlib.icn getchlib.icn iscreen.icn
X
XSHELL = /bin/sh
X
X$(PROGNAME): $(SRC) $(LIB)
X icont -Si 1000 -Sn 2000 -o $(PROGNAME) $(SRC) $(LIB)
X
X# Pessimistic assumptions regarding the environment (in particular,
X# I don't assume you have the BSD "install" shell script).
Xinstall: $(PROGNAME)
X @sh -c "test -d $(DESTDIR) || (mkdir $(DESTDIR) && chmod 755 $(DESTDIR))"
X cp $(PROGNAME) $(DESTDIR)/
X chgrp $(GROUP) $(DESTDIR)/$(PROGNAME)
X chown $(OWNER) $(DESTDIR)/$(PROGNAME)
X @echo "\nInstallation done.\n"
SHAR_EOF
true || echo 'restore of Makefile.dist failed'
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo You have unpacked the last part
exit 0
From icon-group-request@arizona.edu Mon Dec 10 22:09:27 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA23425; Mon, 10 Dec 90 22:09:27 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Mon, 10 Dec 90 22:08 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA11002; Mon, 10 Dec 90
21:02:50 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 10 Dec 90 22:09 MST
Date: 11 Dec 90 03:15:50 GMT
From: midway!ellis.uchicago.edu!goer@handies.ucar.edu
Subject: continuation of the code orgy
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <F00BEDD3CF4340453E@Arizona.edu>
Message-Id: <1990Dec11.031550.9454@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I get annoyed when software requires that I be in this or that
directory, and refuses to poke around a bit, looking for files.
To help remedy the deficiency, I wrote the procedure appended
below.
Right now I've only tested it under Unix and MS-DOS. I'd love
it if someone would repost with additions to make it work under
other operating systems.
-Richard (goer@sophist.uchicago.edu)
############################################################################
#
# Name: getpaths.icn
#
# Title: suspend elements in path environment variable
#
# Author: Richard L. Goerwitz
#
# Version: 1.3
#
############################################################################
#
# Suspends, in turn, the paths supplied as args to getpaths(),
# then all paths in the PATH environment variable. A typical
# invocation might look like:
#
# open(getpaths("/usr/local/lib/icon/procs") || filename)
#
# Note that getpaths() will be resumed in the above context until
# open succeeds in finding an existing, readable file. Getpaths()
# can take any number of arguments.
#
############################################################################
#
# Requires: UNIX or MS-DOS
#
############################################################################
procedure getpaths(base_paths[])
local paths, p
static sep, trailer, trimmer
initial {
if find("UNIX", &features) then {
sep := ":"
trailer := "/"
trimmer := cset(trailer || " ")
}
else if find("MS-DOS", &features) then {
sep := ";"
trailer := "\\"
trimmer := cset(trailer || " ")
}
else stop("getpaths: OS not supported.")
}
suspend !base_paths
paths := getenv("PATH")
\paths ? {
tab(match(sep))
while p := 1(tab(find(sep)), move(1))
do suspend ("" ~== trim(p,trimmer)) || trailer
return ("" ~== trim(tab(0),trimmer)) || trailer
}
end
From icon-group-request@arizona.edu Tue Dec 11 02:07:46 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29311; Tue, 11 Dec 90 02:07:46 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 11 Dec 90 02:07 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA15203; Tue, 11 Dec 90
00:54:35 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 11 Dec 90 02:07 MST
Date: 11 Dec 90 08:50:41 GMT
From: zaphod.mps.ohio-state.edu!usc!samsung!munnari.oz.au!goanna!ok@tut.cis.ohio-state.edu
Subject: RE: continuation of the code orgy
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EFEAA16F3DE3404F2B@Arizona.edu>
Message-Id: <4482@goanna.cs.rmit.oz.au>
Organization: Comp Sci, RMIT, Melbourne, Australia
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <1990Dec11.031550.9454@midway.uchicago.edu>
In article <1990Dec11.031550.9454@midway.uchicago.edu>, goer@ellis.uchicago.edu (Richard L. Goerwitz) writes:
> paths := getenv("PATH")
$PATH is for *programs*. Data files do not belong there.
A better approach would be to allow $env substitution in the argument
to getpaths, e.g.
getpaths("$HOME/lib/foo:$PROJECT/lib", file)
--
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it. -- R. Hochhuth.
From goer%sophist@gargoyle.uchicago.edu Tue Dec 11 07:23:38 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA09506; Tue, 11 Dec 90 07:23:38 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Tue, 11 Dec 90 07:23 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA23936; Tue, 11 Dec 90 08:22:41 CST
Received: by sophist (4.1/UofC3.1X) id AA09758; Tue, 11 Dec 90 08:26:00 CST
Resent-Date: Tue, 11 Dec 90 07:23 MST
Date: Tue, 11 Dec 90 08:26:00 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: RE: continuation of the code orgy
Resent-To: icon-group@cs.arizona.edu
To: zaphod.mps.ohio-state.edu!usc!samsung!munnari.oz.au!goanna!ok@tut.cis.ohio-state.edu
Cc: icon-group@arizona.edu
Resent-Message-Id: <EFBE814EEC334052AF@Arizona.edu>
Message-Id: <9012111426.AA09758@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To:
zaphod.mps.ohio-state.edu!usc!samsung!munnari.oz.au!goanna!ok@tut.cis.ohio-state.edu
X-Vms-Cc: icon-group@Arizona.edu
$PATH is for *programs*. Data files do not belong there.
A relevant consideration. BUT: Icon programs are often unpacked into
user directories, and people aren't as careful about separating files
into lib/src/bin as you might suppose (nor should they necessesarily
be).
A better approach would be to allow $env substitution in the argument
to getpaths, e.g.
getpaths("$HOME/lib/foo:$PROJECT/lib", file)
I utilized the PATH environment variable because Unix and MS-DOS happen to
share this feature. It would be easy enough to change the particular
environment variable used, according to the OS, but when you start put-
ting $STRINGS into the arguments, you are not going to be able to run
the program under anything but Unix.
What I'd really like to see at this point is some revisions to the code
along the lines you suggested. Can this be done in a way that will make
the program broadly useful?
-Richard (goer@sophist.uchicago.edu)
From icon-group-request@arizona.edu Tue Dec 11 14:54:42 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA27425; Tue, 11 Dec 90 14:54:42 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 11 Dec 90 14:54 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA01894; Tue, 11 Dec 90
13:47:05 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 11 Dec 90 14:54 MST
Date: 11 Dec 90 21:42:51 GMT
From: news@psuvax1.cs.psu.edu
Subject: iconx.hdr size on a Sun-4.
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EF7F80EA3593405DB0@Arizona.edu>
Message-Id: <Fnx$o1s3@cs.psu.edu>
Organization: Penn State Computer Science
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
12.8k is a little large. The changes below will reduce the size to
2.6k. Apply the patch below to src/icont/ixhdr.c, and add the
following to config/unix/sun4/define.h:
#define MaxHdr 2688
#define UseFakeFunctionsInHdr
UseFakeFunctionsInHdr will replace some standard C library functions
with smaller and simpler versions in ixhdr.c.
This may have benefit for systems other than Sun-4s; I haven't tried.
The real trick is to reduce the header to 20 bytes.
--
Felix Lee flee@cs.psu.edu
*** /tmp/,RCSt1a04604 Tue Dec 11 16:30:01 1990
--- ixhdr.c Tue Sep 11 19:22:57 1990
***************
*** 30,35 ****
--- 30,61 ----
#define Iconx IconxPath
#endif /* Iconx */
+ #ifdef UseFakeFunctionsInHdr
+ /* fake functions to reduce executable size. */
+ novalue exit(x) int x; { _exit(x); }
+
+ /* small, inefficient strcpy(). */
+ char * strcpy(a, b) register char * a; register char * b;
+ {
+ while (*a++ = *b++) ;
+ return a; /* note! this is incompatible with real strcpy */
+ }
+ /* small, inefficient strlen(). */
+ int strlen(s) char * s;
+ {
+ register char * p;
+ while (*p++) ;
+ return p - s;
+ }
+ /* small, inefficient strcat(). */
+ char * strcat(a, b) register char * a; register char * b;
+ {
+ while (*a++) ;
+ while (*a++ = *b++) ;
+ return a; /* note! this is incompatible with real strcat */
+ }
+ #endif UseFakeFunctionsInHdr
+
novalue main(argc, argv)
int argc;
char **argv;
From icon-group-request@arizona.edu Thu Dec 13 05:27:38 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA13790; Thu, 13 Dec 90 05:27:38 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 13 Dec 90 05:27 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA17639; Thu, 13 Dec 90
04:18:03 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 13 Dec 90 05:27 MST
Date: 12 Dec 90 13:37:46 GMT
From: jvb@cs.duke.edu
Subject: public domain/free version
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EE3C5F1089E34072AD@Arizona.edu>
Message-Id: <661009065@helios.cs.duke.edu>
Organization: Duke University Computer Science Dept.; Durham, N.C.
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I will be teaching a programming languages course this Spring and am
looking to teach a string manipulation language. ICON is one natural
choice. However, I have a zero budget. This leaves me with awk as
my only choice. I don't think it is bad choice, but ICON would be better.
Is there a free ICON interpretter out there?
Jack
From icon-group-request@arizona.edu Thu Dec 13 06:30:54 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA15025; Thu, 13 Dec 90 06:30:54 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 13 Dec 90 06:30 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA20514; Thu, 13 Dec 90
05:25:11 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 13 Dec 90 06:30 MST
Date: 12 Dec 90 17:01:31 GMT
From: hub.ucsb.edu!anywhere!aks@ucsd.edu
Subject: RE: public domain/free version
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EE338A503FF3406EA4@Arizona.edu>
Message-Id: <7794@hub.ucsb.edu>
Organization: CCSE, Univ. of CA, Santa Barbara
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <661009065@helios.cs.duke.edu>
In <661009065@helios.cs.duke.edu> jvb@duke.cs.duke.edu (Jack V. Briner, Jr.) writes:
>I will be teaching a programming languages course this Spring and am
>looking to teach a string manipulation language. ICON is one natural
>choice. However, I have a zero budget. This leaves me with awk as
>my only choice. I don't think it is bad choice, but ICON would be better.
>Is there a free ICON interpretter out there?
For the benefit of others, here's Griswold's original posting announcing
Version 8:
From +comp.lang.icon Wed Dec 12 08:56:24 1990
From: ralph@CS.ARIZONA.EDU ("Ralph Griswold")
Newsgroups: comp.lang.icon
Subject: Version 8 of Icon for UNIX
Message-ID: <9003311250.AA18283@megaron.cs.arizona.edu>
Date: 31 Mar 90 12:50:35 GMT
Distribution: inet
Organization: The Internet
Lines: 37
Version 8 of Icon for UNIX systems is now available. This implementation
can be configured for a wide variety of UNIX systems. Configuration
information is provided for 56 different systems, including the Sun
Sparcstation, the DecStation, the NeXT, the DG AViiON, and the Cray-2.
Configurations for new systems can be added with relative ease.
The UNIX distribution includes source code, configuration files,
documentation, the Icon program library (new in Version 8), and
several auxiliary components of Icon.
Version 8 of Icon for UNIX systems can be obtained by anonymous FTP
to cs.arizona.edu. After connecting, cd /icon/v8. Get READ.ME
there for more information.
If you do not have FTP access or prefer to obtain a magnetic tape
and printed documentation, Version 8 of Icon for UNIX can be ordered
~from:
Icon Project
Department of Computer Science
Gould-Simpson Building
The University of Arizona
Tucson, AZ 85721
602 621-2018 (voice)
602 621-4246 (FAX)
The price is $30, payable in US dollars with a check written on a bank
in the United States. Orders also can be charged to MasterCard or Visa.
This price includes shipping by parcel post in the United States, Canada,
and Mexico. Add $10 for air mail delivery to other countries.
Please direct any questions to me, not to icon-project or icon-group.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
--
Alan Stebbens <aks@hub.ucsb.edu>
From goer%sophist@gargoyle.uchicago.edu Thu Dec 13 15:50:14 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA07464; Thu, 13 Dec 90 15:50:14 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Thu, 13 Dec 90 15:49 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA11262; Thu, 13 Dec 90 16:49:36 CST
Received: by sophist (4.1/UofC3.1X) id AA02207; Thu, 13 Dec 90 16:52:40 CST
Resent-Date: Thu, 13 Dec 90 15:49 MST
Date: Thu, 13 Dec 90 16:52:40 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: Iconish b-trees
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EDE56A557013407B36@Arizona.edu>
Message-Id: <9012132252.AA02207@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Has anyone worked on b-tree algorithms for use in Icon - i.e. on
b-trees which use hash tables or other built-in Iconish data struc-
tures, as part of their implementation. I'm just curious whether
I need to think this stuff through from scratch.
-Richard
From goer%sophist@gargoyle.uchicago.edu Thu Dec 13 18:05:50 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA10873; Thu, 13 Dec 90 18:05:50 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Thu, 13 Dec 90 18:05 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA14286; Thu, 13 Dec 90 19:05:13 CST
Received: by sophist (4.1/UofC3.1X) id AA02487; Thu, 13 Dec 90 19:08:17 CST
Resent-Date: Thu, 13 Dec 90 18:05 MST
Date: Thu, 13 Dec 90 19:08:17 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: Iconish b-trees
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EDD2763741A34077AB@Arizona.edu>
Message-Id: <9012140108.AA02487@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Blasted noisy lines. I'll try again.
Has anyone given any thought to the question of how b-trees might best
be implemented in Icon, taking advantage data structures like tables
and sets?
-Richard (goer@sophist.uchicago.edu)
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Sat Dec 15 10:36:39 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA24856; Sat, 15 Dec 90 10:36:39 -0700
Received: by uwm.edu; id AA04923; Sat, 15 Dec 90 11:36:30 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Sat, 15 Dec 90 10:55:06 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Sat, 15 Dec 1990 07:36 CDT
Date: Sat, 15 Dec 1990 07:36 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Draw Poker Game
To: icon-group@cs.arizona.edu
Message-Id: <67EEF267C0600950@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Since the submission of the solitaire game, I felt it might be nice if I
could contribute one. Here's a draw poker game. I use ICON on VAX/VMS 5.2
with VT terminals, so I do everything with ANSI escape sequences. I also
realize that I could have done some of the table manipulations more
efficiently, but I thought in this case, tab["key"] := something, helped
the readability of the code. Invoke it with ICONX DRAW [credits]. The
parameter is how much virtual money you want to start with. 3 is default.
Have fun!
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
#########################################################
# #
# DRAW.ICN 12/15/90 BY TENAGLIA #
# #
# SIMPLE BUT FUN DRAW POKER GAME. WORKS ON ANSI SCREEN. #
# USAGE : ICONX DRAW [starting credits] #
# #
#########################################################
global money, message
procedure main(param)
money := integer(param[1]) | 3
write("\e[2J\e[2H \e#3\e[1;7mDRAW : Nothing Wild\e[m")
write(" \e#4\e[1;7mDRAW : Nothing Wild\e[m")
repeat
{
deck := shuffle()
message := ""
hand := []
every 1 to 5 do put(hand,pop(deck))
display(hand,1,4)
repeat
{
keep := obtain("\e[12;1fKeep which ones (1 2 3 4 5):\e[J")
if map(input("\e[12;50fAre you sure y/n :\e[K"))[1] == "y" then break
}
all := set() ; every i := 1 to 5 do insert(all,i)
every delete(all,integer(!keep))
every hand[!all] := pop(deck)
money +:= evaluate(hand)
display(hand,1,15)
if map(input("\e[23;1fAnother game? y/n :\e[K"))[1] ~== "y" then break
}
write("\e[2J\e[H")
end
#
# THIS SECTION OBTAINS THE VALIDATES INPUT
#
procedure obtain(prompt)
bad := 0
repeat
{
nums := parse(input(prompt),' \t,')
every num := !nums do
{
integer(num) | { input(num || " not a number. Press <RETURN>") ; bad := 1 ; next }
(integer(num) > 0) | { input(num || " must be between 1 and 5. Press <RETURN>") ; bad := 1 ; next }
(integer(num) < 6) | { input(num || " must be between 1 and 5. Press <RETURN>") ; bad := 1 ; next }
}
(bad = 1) | return nums
}
end
#
# THIS ROUTINE DISPLAYS THE CURRENT HAND AT THE GIVEN X,Y COORDINATES
#
procedure display(cards,x,y)
all := []
every card := !cards do
{
j := y
if find(card[2],"CS") then card := "\e[1;7m" || card || "\e[m"
shape := ["\e["||(j+:=1)||";"||x||"f\e(0lqqqqqqqk\e(B"]
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0x " || card || " x\e(B")
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0x x\e(B")
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0x x\e(B")
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0x x\e(B")
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0x " || card || " x\e(B")
put(shape,"\e["||(j+:=1)||";"||x||"f\e(0mqqqqqqqj\e(B")
put(all,shape)
x +:= 14
}
while shape := pop(all) do every writes(!shape)
writes(message,"\e[",y+2,";",x-3,"fCredits\e[K")
writes("\e[",y+3,";",x-5,"f \e[1m",right(money,7),"\e[m\e[K")
end
#
# THIS ROUTINE SHUFFLES THE CARD DECK
#
procedure shuffle()
static faces, suits
local cards
initial {
&random := map(&clock,":","7") # initial on multiple shuffles
faces := ["2","3","4","5","6","7","8","9","T","J","Q","K","A"]
suits := ["D","H","C","S"]
}
cards := []
every put(cards,!faces || !suits)
swaps := 52 + ?12
every 1 to swaps do cards[?52] :=: cards[?52]
return cards
end
#
# THIS SECTION EVALUATES THE FINAL HAND, TALLIES WINNINGS OR LOOSINGS
#
procedure evaluate(cards)
static hash1,hash2
initial {
hash1 := "23456789TJQKA"
hash2 := "CSHD"
}
temp := table(0) ; suit := table(0) ; result := table(0)
four := 0 ; three := 0 ; twopair := 0 ; job := 0 ; points := -1
flush := 0 ; full := 0 ; royal := 0 ; straight:= 0 ; pair:= 0
every card := !cards do
temp[card[1]] +:= 1
every tmp := key(temp) do
case temp[tmp] of
{
4 : { result["four"] := 1 ; result["job"] := 1 }
3 : { result["three"] := 1 ; result["job"] := 1 }
2 : { result["pair"] +:= 1 ; result["job"] := if find(tmp,hash1) > 9 then 1 }
}
if result["pair"] = 2 then { result["twopair"] := 1 ; result["job"] := 1 }
every card := !cards do suit[card[2]] +:= 1
every tmp := key(suit) do if suit[tmp] = 5 then { result["flush"] := 1 ; result["job"] := 1 }
tmp := sort(cards) ; test := ""
every card := !tmp do test ||:= card[1]
if (result["three"] = 1) & (result["pair"] = 1) then { result["full"] := 1 ; result["job"] := 1 }
if find(test,hash1) then
{
result["straight"] := 1
result["job"] := 1
if test[1] == "T" then result["royal"] := 1
}
if result["job"] = 1 then points +:= 1
if result["twopair"] = 1 then points +:= 1
if result["three"] = 1 then points +:= 5
if result["full"] = 1 then points +:= 10
if result["flush"] = 1 then points +:= 10
if result["straight"]= 1 then points +:= 10
if result["four"] = 1 then points +:= 100
if result["royal"] = 1 then points +:= 500
message := "\e[14;1fHand Evaluation -> "
every thing := key(result) do message ||:= thing || ", "
return points
end
#
# THIS ROUTINE PARSES A STRING WITH RESPECT TO SOME DELIMITER
#
procedure parse(line,delims)
static chars
chars := &cset -- delims
tokens := []
line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
return tokens
end
#
# THIS ROUTINE PROMPTS FOR INPUT AND RETURNS A STRING
#
procedure input(prompt)
writes(prompt)
return read()
end
From icon-group-request@arizona.edu Sun Dec 16 11:10:25 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28760; Sun, 16 Dec 90 11:10:25 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Sun, 16 Dec 90 11:10 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA03555; Sun, 16 Dec 90
09:50:35 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 16 Dec 90 11:10 MST
Date: 15 Dec 90 02:04:05 GMT
From: snorkelwacker.mit.edu!usc!zaphod.mps.ohio-state.edu!mips!daver!kcdev!obrien@bloom-beacon.mit.edu
Subject: klondike
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EBB0FCF68D03408C28@Arizona.edu>
Message-Id: <1259@kcdev.UUCP>
Organization: AT&T Kansas City, MO.
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Would some kind person send me sector 5 of the unix version of klondike.
I can not seem to get the one I captured to download to my machine.
Please send to obrien@spam
because this feed appears to be about gone.
--
| John D. O'Brien AT&T Communications Kansas City, MO 64106 |
| Ph(816)654-4085 Home(816)229-7648 |
| Email: obrien@kcdev.UUCP ATTMail: attmail!kc1sur!jdobrien |
| $include {std_disclaimer.h} "Please don't drink and drive" |
From icon-group-request@arizona.edu Sun Dec 16 12:04:55 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29965; Sun, 16 Dec 90 12:04:55 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Sun, 16 Dec 90 12:04 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA06641; Sun, 16 Dec 90
10:56:14 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Sun, 16 Dec 90 12:04 MST
Date: 15 Dec 90 19:21:20 GMT
From: midway!quads.uchicago.edu!goer@uunet.uu.net
Subject: RE: Draw Poker Game
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EBA96CBD07234086BF@Arizona.edu>
Message-Id: <1990Dec15.192120.1009@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <67EEF267C0600950@mis.mcw.edu>
In article <67EEF267C0600950@mis.mcw.edu>
TENAGLIA@mis.mcw.edu (Chris Tenaglia - 257-8765) writes:
>global money, message
>procedure main(param)
> money := integer(param[1]) | 3
> write("\e[2J\e[2H \e#3\e[1;7mDRAW : Nothing Wild\e[m")
^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^
I love to try to port people's things to Unix, but it's sometimes
pretty hard. The code above is part of a really neat game, and I
like it a lot. But unless a person happens to know ANSI escape se-
quences like the back of his or her hand, it's kinda hard to know
what is going on. It's also a fact that most ANSI terminals don't
really implement the full, exact ANSI standard, and in general peo-
ple (at least here at the U of Chicago) are using Wyse, Televideo,
or VT-100 terminals (or emulators).
It's hard to say this, especially when the code is otherwise so clear
and clean, but my own personal observation is that code which assumes
hard-coded screen control 1) is hard to read, 2) is harder to main-
tain, and 3) is very tedious to port.
One solution (the one used in the klondike game) is to make all the
screen control sequences into global variables, and put them together
in one place, so they can easily be altered. If the global variables
are mnemonic, this solves 1 and 2, but leaves 3 still up in the air.
(I've written a lot of code that has all three problems, so don't
take this as a flame.) The workability of the "klondike" solution is
evinced by the fact that I was able to port it to Unix in a very short
period of time and repost. I admit that the repost was something of a
hack. When the next klondike version comes out I'll do a more serious
job. The mnemonic global variables really helped.
Another solution is to isolate screen control sequences in a single
procedure, which would be called mnemonically. This solution is not
perfect, because it is not always as easy to read as the "klondike"
solution. But is does make maintenance a snap, and leaves would-be
port-ers with very little work to do. I'll give a little example
below that will show how things can be done this way, and yet kept
readable:
> write("\e[2J\e[2H \e#3\e[1;7mDRAW : Nothing Wild\e[m")
output("clear")
output("goto",1,2)
writes(" ")
output(whatever \e#3 does)
output("bold-reverse") # or output("bold"); output("reverse") ???
write("DRAW : Nothing Wild")
output("normal")
By doing things this way, even someone who doesn't know the least bit
about ANSI screen codes will be able to understand what is going on.
What is more, no changes will be required if, say, some escape sequence
needs to be changed. In fact, one could insert codes for a _whole dif-
ferent terminal_ and it wouldn't require changing a single scratch of
the above code. All changes would be isolated within the output pro-
cedure.
I admit that things are more bulky this way. But you don't have to have
your ANSI chart out while programming. And in fact, you don't even have
to think about what sort of terminal you're using. Nor does anyone else
who reads your code. The sequence output("clear") is infinitely more
clear, portable, and maintainable than "\e[2J"!
One more bit that might be useful to inject here: Most terminals can han-
dle 24 lines of text. Not all can handle 25. To hit the majority of
users, keep screen I/O within a range of 24 lines.
I hope that this will help, and not seem like a gratuitous flame!
-Richard
From mlfarm!ron@hsi.hsi.com Mon Dec 17 05:48:21 1990
Received: from hsi.hsi.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29256; Mon, 17 Dec 90 05:48:21 -0700
Received: by hsi.hsi.com (5.61+++/1.34)
id AA29734; Mon, 17 Dec 90 07:46:30 -0500
Received: by mlfarm.com (smail2.5)
id AA09251; 17 Dec 90 06:16:37 EST (Mon)
To: icon-group@cs.arizona.edu
In-Reply-To: goer@quads.uchicago.edu's message of Dec 15 19:21:20 GMT
Subject: RE: Draw Poker Game
Message-Id: <9012170616.AA09251@mlfarm.com>
Date: 17 Dec 90 06:16:37 EST (Mon)
From: mlfarm!ron@hsi.hsi.com (Ronald Florence)
I'd like to add a strong second to Richard Goerwitz's comments on code
portability. One of the most welcome features of Icon is the
implementation independence of the code. With few exceptions, Icon
code works on a broad range of machines. How depressing, then, to
discover valuable utilites and clever games which require hours of
porting with an editor because of hard-coded screen-control escape
sequences. Richard Goerwitz's Icon termcap library, which includes
ms-dos entries, is one solution. For those who don't want to use the
termcap code, screen control sequences can be isolated in global
strings or functions, so that porting doesn't require line-by-line
changes of an entire program.
While I'm griping, I'd urge that program instructions omit
implementation-dependent exceptions:
> # DRAW.ICN 12/15/90 BY TENAGLIA #
> # #
> # SIMPLE BUT FUN DRAW POKER GAME. WORKS ON ANSI SCREEN. #
> # USAGE : ICONX DRAW [starting credits] #
If I'm not wrong, the need for `iconx' before the program name is
confined to ms-dos and VMS. Users of those systems surely know how to
run Icon programs on their systems.
My comments are not in any way intended as a flame of Chris Tenaglia's
excellent game, which would probably work unchanged on some of the
terminals here. With a few changes that would be easy when the code
is written, though time-consuming later, the game would work right off
the icon-group mailing list on any terminal and operating system
running Icon.
--
Ronald Florence ron@mlfarm.com
From icon-group-request@arizona.edu Mon Dec 17 06:49:02 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00502; Mon, 17 Dec 90 06:49:02 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Mon, 17 Dec 90 06:48 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA02160; Mon, 17 Dec 90
05:34:50 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Mon, 17 Dec 90 06:48 MST
Date: 17 Dec 90 13:15:23 GMT
From: eru!hagbard!sunic!sics.se!sics!soder@bloom-beacon.mit.edu
Subject: Exit codes in SunOS 4.1
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EB0C5B1AA563408EBB@Arizona.edu>
Message-Id: <SODER.90Dec17141522@basm.inmic.se>
Organization: Swedish Institute of Microelectronics, Kista
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Has anybody else noticed this:
Problem: Icon programs return spurious (?) exit codes under
recent versions of SunOS. When terminating normally the exit
code is an unpredictable small integer, sometimes even
negative (as reported by /bin/csh).
The problem didn't appear until I ported some software we
developed to SunOS 4.0.1 for the Sun 386i. Now the same
symptom appears when porting the software to a SPARCstation
1+ under SunOS 4.1. (The 4.0.1 for the 386i is more similar
to 4.1 than 4.0.3 for the SPARC.)
My conclusion from browsing the Icon source is that even a
'procedure main (...)' that just flows out through its 'end'
executes a proper Unix 'exit'. Can anybody confirm that?
(Under these OSes a C program that just flows out through
its final brace does not return a predictable return code.)
Reply to me and I'll post a summary. Thanks.
Hakan
----------------------------------------------------
Hakan Soderstrom Phone: +46 (8) 752 1138
NMP-CAD Fax: +46 (8) 750 8056
P.O. Box 1193 E-mail: soder@nmpcad.se
S-164 22 Kista, Sweden
--
----------------------------------------------------
Hakan Soderstrom Phone: +46 (8) 752 1138
NMP-CAD Fax: +46 (8) 750 8056
P.O. Box 1193 E-mail: soder@nmpcad.se
S-164 22 Kista, Sweden
From goer%sophist@gargoyle.uchicago.edu Mon Dec 17 08:54:29 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA03897; Mon, 17 Dec 90 08:54:29 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Mon, 17 Dec 90 08:53 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA08765; Mon, 17 Dec 90 09:53:13 CST
Received: by sophist (4.1/UofC3.1X) id AA01710; Mon, 17 Dec 90 09:56:15 CST
Resent-Date: Mon, 17 Dec 90 08:53 MST
Date: Mon, 17 Dec 90 09:56:15 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: followup on games
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EAFAD8812CC34091AC@Arizona.edu>
Message-Id: <9012171556.AA01710@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
I'd like to add a strong second to Richard Goerwitz's comments on code
portability. One of the most welcome features of Icon is the
implementation independence of the code. With few exceptions, Icon
code works on a broad range of machines. How depressing, then, to
discover valuable utilites and clever games which require hours of
porting with an editor because of hard-coded screen-control escape
sequences. Richard Goerwitz's Icon termcap library, which includes
ms-dos entries, is one solution...
...albeit a slightly clumsy one for DOS. For DOS the only advantage to us-
ing these routines is that they allow you to move your code unaltered over
to Unix. And you don't have to know the slightest thing about Unix, other
than the basic termcap codes (e.g. "so" for boldface, etc.). Termcap files,
though, don't know about color, about the difference between bold and re-
verse video, and can't take advantage of really fancy terminal features.
It's a mixed bag.
I'll be glad to send the full DOS/UNIX Icon termlib-type routines in their
latest incarnation to anyone that asks. The most recent changes have been
a full DOS implementation.
The main point is just to isolate screen control codes in a single proce-
dure, and to output them via a separate routine. Anyone who does this is
going to make porting his or her code to another OS or output device a
real snap.
While I'm griping, I'd urge that program instructions omit
implementation-dependent exceptions:
> # DRAW.ICN 12/15/90 BY TENAGLIA #
> # #
> # SIMPLE BUT FUN DRAW POKER GAME. WORKS ON ANSI SCREEN. #
> # USAGE : ICONX DRAW [starting credits] #
If I'm not wrong, the need for `iconx' before the program name is
confined to ms-dos and VMS. Users of those systems surely know how to
run Icon programs on their systems.
I've only used Icon under Unix and MS-DOS. I'm sure that's pretty typical.
I mean, few have run it under more than one or two operating systems. I
gather that Chris is MS-DOS/VMS. Just so happens that these don't support
direct execution of Icon programs (as you point out). (For those who don't
know, "direct execution" means, in practical terms, that you can just type
the name of the program, and don't need to type in "iconx").
My comments are not in any way intended as a flame of Chris Tenaglia's
excellent game, which would probably work unchanged on some of the
terminals here.
Yes, we don't want to discourage Chris from posting! He's written some very
interesting stuff. And he's one of the few VMS users we see posting, so it
is very nice to have his input (esp. for people like me who hardly know VMS
from MVS). Incidentally, the game runs here on my Xenix console.
-Richard
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Mon Dec 17 15:15:35 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA17643; Mon, 17 Dec 90 15:15:35 -0700
Received: by uwm.edu; id AA08233; Mon, 17 Dec 90 16:15:03 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Mon, 17 Dec 90 14:13:51 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Mon, 17 Dec 1990 13:43 CDT
Date: Mon, 17 Dec 1990 13:43 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: crt handler library
To: icon-group@cs.arizona.edu
Message-Id: <2D9076E640200646@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Well, appararently raw ansi escape sequences in write() statements are not
as commonplace as I thought. I put together a video manipulator library
collection. Since I only have VT terminals and ansi to work with, I coded
in only those cases. Someone else will have to fill in the rest. These
procedures generate escape sequence strings for write() commands. In places
where this doesn't apply, one would have them return "", and generate the
desired side effect. For example,...
write(crt_dark(),crt_clear(),crt_upper_half(),crt_mode("high","inverse"),
center("Header",39),crt_mode("normal"))
write(crt_lower_half(),crt_mode("high","inverse"),center("Header",39),
crt_mode("normal"))
Would output the header to some screen in double sized characters centered
at the top of the screen in bright, inverse video. This scenario requires
a global variable called TERM that defines the terminal used. On unix
systems a getenv() could probably generate sufficient clues to have this
determined at run time.
Granted, my draw poker game was a quick and dirty implementation. On VMS
screen painting is so slow with ICON that I didn't want to further slow the
application by adding layers of object oriented display managers.
Thanx for the suggestions! Below are 162 lines of code, in 22 or so procedures.
Have fun!
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
#
# CRT.ICN CREATED 12/17/90 BY TENAGLIA
#
# THIS IS A SCREEN FUNCTION LIBRARY. I AM SUBMITTING PARTS PERTAINING TO
# VT,ANSI EMULATION. OTHERS, PLEASE FEEL FREE TO ADD YOURS. UNDER VT
# TERMINAL EMULATION SPECIAL STRINGS BEGINNING WITH ESCAPE X'1B' START
# SEQUENCES THAT DO USEFUL THINGS TO DISPLAYS. THE VT FUNCTIONS RETURN
# THE ESCAPE SEQUENCES. OTHER VIDEO METHODS MAY PERFORM INTERRUPTS, PORT
# OR I/O RETURNING "" TO ACCOMPLISH THE SAME THING.
#
global TERM # DEFINE A GLOBAL VARIABLE CALLED TERM
procedure main() # IT DECLARES THE TERMINAL TYPE. "VT" IS
TERM := "VT" # FOR DEC VT100,2XX,3XX,4XX SERIES.
end # OTHERS MAY BE "X", "4014", "TTY", ETC,...
procedure crt_error()
stop("TERM as (",TERM,") not properly defined.")
end
procedure crt_clear()
case TERM of {
"VT" : return "\e[2J\e[H" # CLEAR SCREEN AND HOME
default : crt_error() }
end
procedure crt_home()
case TERM of {
"VT" : return "\e[H" # MOVE CURSOR TO TOP OF SCREEN LEFT SIDE
default : crt_error() }
end
procedure crt_goto(x,y) # SET CURSOR TO X(COLUMN) Y(ROW) SCREEN POSITION
case TERM of {
"VT" : return "\e[" || y || ";" || x || "f"
default : crt_error() }
end
procedure crt_upper_half() #
case TERM of { # TOP HALF OF DOUBLE WIDTH, DOUBLE HEIGHT CHARS
"VT" : return "\e#3" #
default : crt_error() }
end
procedure crt_lower_half() #
case TERM of { # BOTTOM HALF OF DOUBLE WIDTH, DOUBLE HEIGHT
"VT" : return "\e#4" #
default : crt_error() }
end
procedure crt_mode(p1,p2,p3,p4,p5) #
/p5 := "n/a" # THIS ROUTINE SETS THE OUTPUT
/p4 := "n/a" # ATTRIBUTES FOR CHARACTERS.
/p3 := "n/a" # SOME ENVIRONMENTS MAY USE
/p2 := "n/a" # COLORS.
/p1 := "n/a" #
all := [p1,p2,p3,p4,p5] #
case TERM of { #
"VT" : { #
seq := "\e[" #
every mode := !all do # THESE CAN BE COMBINED MUCH
case mode of # LIKE SETTING BITS.
{ #
"normal : seq ||:= "0;" # NORMAL VIDEO
"high" : seq ||:= "1;" # HIGH INTENSITY
"dim" : seq ||:= "2;" # LOW INTENSITY
"under" : seq ||:= "4;" # UNDERSCORED
"blink" : seq ||:= "5;" # BLINKING
"inverse" : seq ||:= "7;" # INVERSE VIDEO
"conceal" : seq ||:= "8;" # INVISIBLE
default : &null # IGNORE OTHERS
} #
seq[-1] := "m" #
return seq #
} #
default : crt_error() }
end
procedure crt_graphic() #
case TERM of { # TURN ON ANSI LINE GRAPHICS CHARACTERS
"VT" : return "\e(0" #
default : crt_error() }
end
procedure crt_nographic() #
case TERM of { # TURN OFF ANSI LINE GRAPHICS CHARACTERS
"VT" : return "\e(B" #
default : crt_error() }
end
procedure crt_smooth() #
case TERM of { # PUTS CRT IN SMOOTH SCROLLING MODE
"VT" : return "\e[?4h" #
default : crt_error() }
end
procedure crt_jump() #
case TERM of { # PUTS CRT IN JUMP SCROLLING MODE
"VT" : return "\e[?4l" #
default : crt_error() }
end
procedure crt_scroll(t,b) #
/b := "" # SET UP SCROLLING
/t := "" # REGIONS ON THE SCREEN
case TERM of { # T IS THE TOP MARGIN
"VT" : { # B IS THE BOTTOM MARGIN
if (t=="") & (b=="") then return "\e[r" # OMIT B, THEN BOTTOM OF
if b=="" then return "\e[" || t || "r" # SCREEN IS BOTTOM MARGIN
return "\e[" || t || ";" || b || "r" # OMIT B & T TO RESET TO
} # NORMAL FULL SCREEN
default : crt_error() }
end
procedure crt_erase_eol() #
case TERM of { # ERASE CHARACTERS FROM CURSOR TO
"VT" : return "\e[K" # END OF LINE
default : crt_error() }
end
procedure crt_erase_sol() #
case TERM of { # ERASE CHARACTERS FROM CURSOR TO
"VT" : return "\e[1K" # START OF LINE
default : crt_error() }
end
procedure crt_erase_eos() #
case TERM of { # ERASE CHARACTERS FROM CURSOR TO
"VT" : return "\e[J" # END OF SCREEN
default : crt_error() }
end
procedure crt_erase_tos() #
case TERM of { # ERASE CHARACTERS FROM CURSOR TO
"VT" : return "\e[1J" # TOP OF SCREEN
default : crt_error() }
end
procedure crt_light() #
case TERM of { # MAKE SCREEN LIGHT BACKGROUND
"VT" : return "\e[?5h" #
default : crt_error() }
end
procedure crt_dark() #
case TERM of { # MAKE SCREEN DARK BACKGROUND
"VT" : return "\e[?5l" #
default : crt_error() }
end
procedure crt_132() #
case TERM of { # MAKE SCREEN 132 COLUMNS WIDE
"VT" : return "\e[?3h" #
default : crt_error() }
end
procedure crt_80() #
case TERM of { # MAKE SCREEN 80 COLUMNS WIDE
"VT" : return "\e[?3l" #
default : crt_error() }
end
From goer%sophist@gargoyle.uchicago.edu Mon Dec 17 18:26:02 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA23453; Mon, 17 Dec 90 18:26:02 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Mon, 17 Dec 90 18:25 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA23714; Mon, 17 Dec 90 19:25:05 CST
Received: by sophist (4.1/UofC3.1X) id AA02016; Mon, 17 Dec 90 19:28:06 CST
Resent-Date: Mon, 17 Dec 90 18:25 MST
Date: Mon, 17 Dec 90 19:28:06 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: crt_dark()
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EAAB06C827A3409438@Arizona.edu>
Message-Id: <9012180128.AA02016@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
write(crt_lower_half(),crt_mode("high","inverse"),center("Header",39),
crt_mode("normal"))
This approach is good. The better you hide terminal characteristics
behind a high-level interface, the easier it will be to port your
software.
write(crt_dark(),crt_clear(),crt_upper_half()...
One suggestion: Make crt_dark() and crt_clear() and crt_mode() into
a single routine. That way I don't have to go try to modify all the
different procedures. You could, of course, just do this:
procedure output(s)
case s of {
"clear" : crt_clear()
"dark" : crt_dark()
"normal": etc....
This would make porting a snap, and I wouldn't even have to modify the
crt_clear routine. To port your software to Unix, all I'd have to do
is insert my own screen clearing routine in place of crt_clear().
Just some thoughts.
-Richard
From goer%sophist@gargoyle.uchicago.edu Mon Dec 17 22:30:04 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00811; Mon, 17 Dec 90 22:30:04 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Mon, 17 Dec 90 22:29 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA00435; Mon, 17 Dec 90 23:29:17 CST
Received: by sophist (4.1/UofC3.1X) id AA02212; Mon, 17 Dec 90 23:32:18 CST
Resent-Date: Mon, 17 Dec 90 22:29 MST
Date: Mon, 17 Dec 90 23:32:18 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: termcap md/me
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EA88E452B6D3406404@Arizona.edu>
Message-Id: <9012180532.AA02212@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Hmmm. It's true that md and me are present in my termcap entries,
but this isn't discussed in my man pages (Xenix). I note that the
SunOS man pages for sophist here do discuss md/me. I'm no expert
on termcap's history.
-Richard
From mlfarm!ron@hsi.hsi.com Tue Dec 18 07:17:16 1990
Received: from hsi.hsi.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14911; Tue, 18 Dec 90 07:17:16 -0700
Received: by hsi.hsi.com (5.61+++/1.34)
id AA18203; Tue, 18 Dec 90 09:15:33 -0500
Received: by mlfarm.com (smail2.5)
id AA11465; 18 Dec 90 08:26:01 EST (Tue)
To: icon-group@cs.arizona.edu
In-Reply-To: Chris Tenaglia - 257-8765's message of Mon Dec 17 13:43 CDT
Subject: crt handler library
Message-Id: <9012180826.AA11465@mlfarm.com>
Date: 18 Dec 90 08:26:01 EST (Tue)
From: mlfarm!ron@hsi.hsi.com (Ronald Florence)
Chris Tenaglia - 257-8765 writes:
> Well, appararently raw ansi escape sequences in write() statements are not
> as commonplace as I thought. I put together a video manipulator library
> collection. Since I only have VT terminals and ansi to work with, I coded
> in only those cases. Someone else will have to fill in the rest.
> [...] This scenario requires
> a global variable called TERM that defines the terminal used. On unix
> systems a getenv() could probably generate sufficient clues to have this
> determined at run time.
Bravo to Chris for a quick and generous response to comments. His
solution is a great improvement to the chaos of screen-writing code.
Still, a problem remains ...
Ms-dos and VMS implementations, like Chris', are written for systems
which assume that screen displays are on a limited variety of
terminals. Adding another terminal requires hand-coding another
option in each case statement. Most Unix systems automatically
determine the user's terminal-type at login, then use a database of
terminal characteristics (termcap or terminfo) to look up the screen
display sequences. For example, our small system here has ansi
25-line terminals, ansi 43-line terminals, a Wyse 150 emulating a
Wyse50+, a Wyse 99gt emulating a vt220, various vt100 emulations,
laptops emulating whatever their software can do, and occasional
logins from odd places with odd terminals. Users expect all of these
terminals to function with full-screen displays _automatically_.
I'd like to see us arrive at a convention or library of display
functions to simplify the porting of Icon code with full-screen
displays. Perhaps the way to do it would be to include a lookup of
&features in an initialization function, which would then toggle
between a termcap library (for Unix systems), hard-coded ansi
display strings (for ms-dos systems), and a case statement with a
few options (for VMS systems). If we could develop such a library,
porting a game like Chris' to Unix or ms-dos would require only the
linking of an appropriate library during the make.
Am I crazy or fascist to propose this?
--
Ronald Florence ron@mlfarm.com
From nowlin@iwtqg.att.com Tue Dec 18 09:31:54 1990
Message-Id: <9012181631.AA21106@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA21106; Tue, 18 Dec 90 09:31:54 -0700
From: nowlin@iwtqg.att.com
Date: Tue, 18 Dec 90 09:34 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: icon-group@cs.arizona.edu
Subject: Re: crt handler library
> ... Perhaps the way to do it would be to include a lookup of
> &features in an initialization function, which would then toggle
> between a termcap library (for Unix systems), hard-coded ansi
> display strings (for ms-dos systems), and a case statement with a
> few options (for VMS systems). If we could develop such a library,
> porting a game like Chris' to Unix or ms-dos would require only the
> linking of an appropriate library during the make.
>
> Am I crazy or fascist to propose this?
> --
>
> Ronald Florence ron@mlfarm.com
I frequently use the UNIX tput command with read pipes in Icon to define
a series of terminal specific escape sequences before having a program do
fancy stuff with screen output.
If the list of screen attributes is relatively short this is a good
way to populate a few global values at the start of UNIX programs. If
there is some equivalent VMS command then UNIX and VMS could be handled
easily. The PC is pretty standard and set definitions for PC screen
attributes would make more sense. This would make implementing the above
scheme relatively simple.
Here's a small example of what I'm talking about:
global CLEAR, ON, OFF
procedure main()
term_attr_set()
write(CLEAR)
write("\n\n\t",ON,"Happy",OFF," ~ ",ON,"Holidays",OFF,"\n\n")
end
procedure term_attr_set()
CLEAR := \do_tput("clear")
ON := \do_tput("smso")
ON ||:= \do_tput("blink")
OFF := \do_tput("sgr0")
end
procedure do_tput(attr)
local cmd, in, ret
cmd := "tput " || attr
in := open(cmd,"rp")
ret := read(in)
close(in)
return ret
end
Jerry Nowlin
(...!att!iwtqg!nowlin)
From callas@eris.enet.dec.com Tue Dec 18 09:36:24 1990
Received: from decpa.pa.dec.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA21263; Tue, 18 Dec 90 09:36:24 -0700
Received: by decpa.pa.dec.com; id AA27630; Tue, 18 Dec 90 08:17:35 -0800
Message-Id: <9012181617.AA27630@decpa.pa.dec.com>
Received: from eris.enet; by decwrl.enet; Tue, 18 Dec 90 08:17:37 PST
Date: Tue, 18 Dec 90 08:17:37 PST
From: This message sent with 100% recycled bits 18-Dec-1990 1103 <callas@eris.enet.dec.com>
To: icon-group@cs.arizona.edu
Subject: CRT handling
Actually, on VMS systems, there is a termcap-like library of terminals, and
it's easily extensible. Also, the C run-time library contains an implementation
of curses. No doubt there's a way to code an application so that it'll not
port between some unix and VMS, but I've tossed programs around with little
trouble.
Jon Callas
From goer%sophist@gargoyle.uchicago.edu Tue Dec 18 13:43:48 1990
Resent-From: goer%sophist@gargoyle.uchicago.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29612; Tue, 18 Dec 90 13:43:48 -0700
Return-Path: goer@sophist.uchicago.edu
Received: from gargoyle.uchicago.edu by Arizona.edu; Tue, 18 Dec 90 13:42 MST
Received: by gargoyle.uchicago.edu from sophist (sophist.uchicago.edu)
(4.0/1.14) id AA16957; Tue, 18 Dec 90 14:42:45 CST
Received: by sophist (4.1/UofC3.1X) id AA02520; Tue, 18 Dec 90 14:45:45 CST
Resent-Date: Tue, 18 Dec 90 13:43 MST
Date: Tue, 18 Dec 90 14:45:45 CST
From: Richard Goerwitz <goer%sophist@gargoyle.uchicago.edu>
Subject: RE: crt library
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <EA09488C6D6340AA35@Arizona.edu>
Message-Id: <9012182045.AA02520@sophist>
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Jerry Nowlin writes:
global CLEAR, ON, OFF
procedure main()
term_attr_set()
write(CLEAR)
write("\n\n\t",ON,"Happy",OFF," ~ ",ON,"Holidays",OFF,"\n\n")
end
procedure term_attr_set()
CLEAR := \do_tput("clear")
ON := \do_tput("smso")
ON ||:= \do_tput("blink")
OFF := \do_tput("sgr0")
end
etc...
This is a very good solution. All we have to do in order to port the
software to a new OS is to change this one procedure, term_attr_set().
Is it time for a repost of my itlib routines, with the DOS port,
UNIX getch(), getche(), kbhit() hacks, and various support rou-
tines (e.g. clear(), underline(), and other procedures meant to work
even on magic cookie terminals)? The post would not be small. It
would probably need to be sent out as a five-part shar, with a pro-
mise to mail individual copies to people who can't unpack shell ar-
chives. Should I post to alt.sources? Post at all?
I expect that an energetic VMS user could easily code up a set of
equivalent routines for that OS. The basic routines a) read the
termcap database file, 2) check to see what terminal type the user
is using, and then 3) make the codes in the terminal database
available to the user via calls to a procedure called getval().
Output of codes is done through a separate iputs() command, which
takes care of time delays and padding. In most cases, one could
just use writse() instead of iputs, since only the most ornery of
terminals still need silly things like padding.
The only difficulty I envision (and it is hardly a difficulty) is
to work things so that by calling getval() with a Unix capname,
such as "so" (i.e. getval("so")), the VMS port would a) be able to
recognize what "so" means, and b) be able to access its VMS equi-
valent.
I'll make an offer: If someone will make up a set of VMS routines
that can look up a user's terminal type at run-time, and then ac-
cess the database for that terminal by a single routine (e.g.
lookup("clear")), I'll put a wrapper around the procedure that
will be compatible with my Unix/DOS termlib-like routines.
Naturally, it would help if someone doing this had half an eye on
the Unix/DOS termlib-like routines, so that the structure of the
system is analogous to what's already been done by me.
-Richard (goer@sophist.uchicago.edu)
From @po10.andrew.cmu.edu:mss+@andrew.cmu.edu Wed Dec 19 14:28:49 1990
Received: from po10.andrew.cmu.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02468; Wed, 19 Dec 90 14:28:49 -0700
Received: by po10.andrew.cmu.edu (5.54/3.15) id <AA04272> for icon-group@cs.arizona.edu; Wed, 19 Dec 90 16:28:07 EST
Received: via switchmail; Wed, 19 Dec 90 16:28:01 -0500 (EST)
Received: from po10.andrew.cmu.edu via qmail
ID </afs/andrew.cmu.edu/service/mailqs/sq2/QF.AbOdgAC00UdiE2jUJC>;
Sat, 15 Dec 90 16:52:17 -0500 (EST)
Received: from mss.andrew.cmu.edu via qmail
ID </afs/andrew.cmu.edu/service/mailqs/q002/QF.wbOdefW00VsAE0K4MC>;
Sat, 15 Dec 90 16:50:37 -0500 (EST)
Received: from mss.andrew.cmu.edu via qmail
ID </afs/andrew.cmu.edu/usr18/mss/.Outgoing/QF.obOddXi00VsA8AfWNp>;
Sat, 15 Dec 1990 16:49:24 -0500 (EST)
Received: from Messages.7.14.N.CUILIB.3.45.SNAP.NOT.LINKED.mss.andrew.cmu.edu.rt.r3
via MS.5.6.mss.andrew.cmu.edu.rt_r3;
Sat, 15 Dec 1990 16:49:23 -0500 (EST)
Message-Id: <0bOddXa00VsAMAfWFb@andrew.cmu.edu>
Date: Sat, 15 Dec 1990 16:49:23 -0500 (EST)
From: Mark Sherman <mss+@andrew.cmu.edu>
To: icon-group@cs.arizona.edu
Subject: Mac graphics from Icon
I'm probably displaying some ignorance, but...
Does anyone know of a way to get native Macintosh graphics from within
Icon on the Macintosh? In reading the TR on personalized interpreters, I
am led to believe that the facility is only available on Unix machines,
so trying to build my own Mac system may not be an answer.
-Mark
From ralph Wed Dec 19 14:40:50 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA02880; Wed, 19 Dec 90 14:40:50 -0700
Date: Wed, 19 Dec 90 14:40:49 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9012192140.AA04124@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Wed, 19 Dec 90 14:40:49 MST
To: mss+@andrew.cmu.edu
Subject: Re: Mac graphics from Icon
Cc: icon-group
Personalized interpreters are available only under UNIX Icon. They
just make it possible to add functionality without having to have
or recompile the entire source.
You can add functionality to any version of Icon, given the source
code and enough knowledge of Icon internals.
I won't attempt to characterize the difficulty of accessing the
Macintosh Toolbox in any general way, however.
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
+1 602 621 6609 ralph@cs.arizona.edu uunet!arizona!ralph
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Thu Dec 20 13:02:52 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA11489; Thu, 20 Dec 90 13:02:52 -0700
Received: by uwm.edu; id AA12489; Thu, 20 Dec 90 14:02:17 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Thu, 20 Dec 90 13:41:03 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Thu, 20 Dec 1990 08:30 CDT
Date: Thu, 20 Dec 1990 08:30 CDT
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Code Dichotomy
To: icon-group@cs.arizona.edu
Message-Id: <5D628D4580200921@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Why is it, The prettier (and more consistent) the user interface, The
uglier the code? Or maybe this is the mark of true software craftsman,
to couple elegant looking (and readible) code with elegant looking and
consistent functionality. Any comments?
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From djbailey@skyler.mavd.honeywell.com Thu Dec 20 14:55:06 1990
Message-Id: <9012202155.AA15557@megaron.cs.arizona.edu>
Received: from skyler.mavd.honeywell.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA15557; Thu, 20 Dec 90 14:55:06 -0700
Date: 20 Dec 90 15:52:00 CDT
From: "BAILEY, DON" <djbailey@skyler.mavd.honeywell.com>
Subject: Re: Code Dichotomy
To: "icon-group" <icon-group@cs.arizona.edu>
>Why is it, The prettier (and more consistent) the user interface, The
>uglier the code? Or maybe this is the mark of true software craftsman,
>to couple elegant looking (and readible) code with elegant looking and
>consistent functionality. Any comments?
I have a theory that there is a specific amount of mental effort
associated with solving a problem. You can move the effort
around but you can't get rid of it. Computer programs that are driven
by the real world always seem to have some "naughty bits" that just
aren't very nice. If you do solve a real world problem without any
"naughty bits" you have done well. (Of course, your solution is
resting on someone else's naughty bits in the language processor
or operating system.)
From icon-group-request@arizona.edu Thu Dec 20 23:54:59 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA28309; Thu, 20 Dec 90 23:54:59 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Thu, 20 Dec 90 23:54 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA21082; Thu, 20 Dec 90
22:46:28 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Thu, 20 Dec 90 23:54 MST
Date: 21 Dec 90 06:13:05 GMT
From: midway!ellis.uchicago.edu!goer@handies.ucar.edu
Subject: itlib on alt.sources
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <E82185301DA340C53F@Arizona.edu>
Message-Id: <1990Dec21.061305.25347@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Rather than mail out individual copies of my Icon termlib-like
routines, I decided to post them to alt.sources. People who don't
get alt.sources, write me. I will send out individual copies to
those who request them. I've burdened this non-source group with
a lot of source code already, and I believe it will be much bet-
ter to put this rather largish posting in a more appropriate place.
This is a repost, but I believe it is justified by the improvements
I've made, and also by the simple fact that I was asked to post them
again.
-Richard (goer@sophist.uchicago.edu)
From reid@ctc.contel.com Fri Dec 21 06:51:16 1990
Received: from ctc.contel.com (turing.ctc.contel.com) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA09522; Fri, 21 Dec 90 06:51:16 -0700
Received: from absurd.ctc.contel.com by ctc.contel.com (4.0/SMI-4.0)
id AA11474; Fri, 21 Dec 90 08:50:45 EST
Date: Fri, 21 Dec 90 08:50:45 EST
From: reid@ctc.contel.com (Tom Reid x4505)
Message-Id: <9012211350.AA11474@ctc.contel.com>
To: djbailey@skyler.mavd.honeywell.com, icon-group@cs.arizona.edu
Subject: Re: Code Dichotomy
Cc: reid@ctc.contel.com, sel@ctc.contel.com
=
= >Why is it, The prettier (and more consistent) the user interface, The
= >uglier the code? Or maybe this is the mark of true software craftsman,
= >to couple elegant looking (and readible) code with elegant looking and
= >consistent functionality. Any comments?
=
=
= I have a theory that there is a specific amount of mental effort
= associated with solving a problem. You can move the effort
= around but you can't get rid of it. Computer programs that are driven
= by the real world always seem to have some "naughty bits" that just
= aren't very nice. If you do solve a real world problem without any
= "naughty bits" you have done well. (Of course, your solution is
= resting on someone else's naughty bits in the language processor
= or operating system.)
=
Ugly or voluminous code is an indication that the abstractions supported
by the language do not support (well) those of the problem domain.
Traditional languages supported "algorithmic" programming well. ICON
has excellent list processing and stream processing abstractions. There
are few (any?) languages that have graphics or user interface abstractions.
Still evolving libraries (Interviews, X, OpenLook, Motif) are the
state-of-the-art. Visual languages are still in their infancy.
Of course, the limits of how well a basically one-dimensional technology
(traditional text languages) can describe two and three dimensional
problem domains is another question.
From nowlin@iwtqg.att.com Fri Dec 21 07:22:01 1990
Message-Id: <9012211422.AA10123@megaron.cs.arizona.edu>
Received: from att.att.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA10123; Fri, 21 Dec 90 07:22:01 -0700
From: nowlin@iwtqg.att.com
Date: Fri, 21 Dec 90 07:36 CST
Original-From: iwtqg!nowlin (Jerry D Nowlin +1 312 979 7268)
To: icon-group@cs.arizona.edu
Subject: Re: Code Dichotomy
> >Why is it, The prettier (and more consistent) the user interface, The
> >uglier the code? Or maybe this is the mark of true software craftsman,
> >to couple elegant looking (and readible) code with elegant looking and
> >consistent functionality. Any comments?
>
> I have a theory that there is a specific amount of mental effort
> associated with solving a problem. You can move the effort
> around but you can't get rid of it. Computer programs that are driven
> by the real world always seem to have some "naughty bits" that just
> aren't very nice. If you do solve a real world problem without any
> "naughty bits" you have done well. (Of course, your solution is
> resting on someone else's naughty bits in the language processor
> or operating system.)
When there's a finite amount of mental effort available (I'd extend this to
a finite amount of available time and other computing resources when
working in the real world) you have to balance that time between making it
easy for the people that use your code, making it easy for the people that
maintain your code, and making it easy on yourself as the programmer. The
usual balance seems to be making it easy on the user and the programmer and
the maintainer gets the short end of the stick. That explains the ugly
code. A reason for this balance is that too many programmers think their
code is good and why would they or someone else ever want to change it.
These are usually (no slur intended) non-real world types who don't have
managers or users to pick at all their nits or market pressure to
constantly improve their products.
The balance should be to make it easy for the user first. If they don't
buy/use your software who cares how elegant it is or how easy it is to
maintain. The second priority should be maintainability. Maintainability
doesn't just mean fixing bugs is easy. It also means modifying your code
to add functionality is easy. If your software is good someone will one-up
you and you'd better be able to leap frog them fast when they do. Finally,
the ease of development/implementation should be considered but never at
the expense of the first two priorities. You should be in this for the
long haul. One shot programs are for personal use. To treat distributed
software that way is naive.
Another thing that hurts software is lack of testing. Software is like
wine with testing being analogous to aging. It should never be released
before its time. Too much software currently out there is the equivalent
of Ripple or Boones Farm.
Jerry Nowlin (...!att!iwtqg!nowlin)
From icon-group-request@arizona.edu Fri Dec 21 12:13:47 1990
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA20751; Fri, 21 Dec 90 12:13:47 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Fri, 21 Dec 90 12:13 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA04971; Fri, 21 Dec 90
10:54:45 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Fri, 21 Dec 90 12:13 MST
Date: 21 Dec 90 17:08:47 GMT
From: swrinde!zaphod.mps.ohio-state.edu!casbah.acns.nwu.edu!accuvax.nwu.edu!midway!ellis.uchicago.edu!goer@ucsd.edu
Subject: itlib (blanket explanation)
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <E7BA5263FCF340C7B8@Arizona.edu>
Message-Id: <1990Dec21.170847.6080@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
My mailbox was pretty full this morning, mostly with requests for
the termlib-like routines I said I'd put on alt.sources. I again
state that I am happy to send out individual copies to people who
don't get alt.sources.
I received a couple of questions regarding programs I've posted be-
fore - programs which were packed with earlier versions of itlib.
The questions were mostly along the lines of, "Does the current ver-
sion of itlib and associated routines serve as a drop-in replace-
ment for earlier itlib incarnations?" The answer is "yes." This
means that anyone running
klondike - Unix _hack_
hebcalen - Unix port of Alan Corre's calendar program
snake - cute "game"
can use the new routines if he/she desires (if the old ones work
fine, though, I really don't see the point).
Itlib is now packed 1) with generalized routines for turning on empha-
size and underline modes (yes, they even work on many magic cookie
terminals), 2) implementations for getch() and getche() under Unix,
and 3) a DOS port of the itlib routines themselves. Included is a DOS
termcap file. I forget where I got it. It works, but could surely
use some messaging. Many of these changes and improvements were
posted to the icon-group. This posting integrates them all into one
package.
I'm sorry to have taken so much space. It just seemed sensible to
post the information I'm being asked for repeatedly by email.
The offer still stands that if someone creates a set of equivalent
routines for VMS, I'll put a wrapper around them that will render
them compatible with itlib.
-Richard Goerwitz (goer@sophist.uchicago.edu)
From cjeffery Fri Dec 21 13:25:44 1990
Received: from caslon.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA23022; Fri, 21 Dec 90 13:25:44 -0700
Date: Fri, 21 Dec 90 13:25:39 -0700
From: "Clinton Jeffery" <cjeffery>
Message-Id: <9012212025.AA01028@caslon.cs.arizona.edu>
Received: by caslon.cs.arizona.edu; Fri, 21 Dec 90 13:25:39 -0700
To: reid@ctc.contel.com
Cc: djbailey@skyler.mavd.honeywell.com, icon-group@cs.arizona.edu,
sel@ctc.contel.com
In-Reply-To: Tom Reid x4505's message of Fri, 21 Dec 90 08:50:45 EST <9012211350.AA11474@ctc.contel.com>
Subject: Code Dichotomy
> Of course, the limits of how well a basically one-dimensional technology
> (traditional text languages) can describe two and three dimensional
> problem domains is another question.
Text languages are only one dimensional when you lay them out "flat" in
source files. When they execute, they are something else; recursion
(for example) just doesn't seem one-dimensional to me.
Outside the realm of graphics and visualization modern text languages are
routinely used to solve multidimensional problems. A language's support
for multidimensional problem domains might be limited by its control and
data structures, but I think the bigger problem for graphics applications
(as well as natural language processing) is the "semantic gap" between the
source language and the problem domain. Semantic gap can, I think, be
addressed linguistically once it is understood.
From ralph Sat Dec 22 07:39:40 1990
Received: from cheltenham.cs.arizona.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA18753; Sat, 22 Dec 90 07:39:40 -0700
Date: Sat, 22 Dec 90 07:39:38 MST
From: "Ralph Griswold" <ralph>
Message-Id: <9012221439.AA05788@cheltenham.cs.arizona.edu>
Received: by cheltenham.cs.arizona.edu; Sat, 22 Dec 90 07:39:38 MST
To: icon-group
Subject: ProIcon 2.0
Version 2.0 of ProIcon, an implementation of Icon for the Macintosh,
is now available.
ProIcon is a stand-alone application with a standard Macintosh interface.
It includes a capable program editor and has facilities for compiling
and running Icon programs, setting program options, managing windows,
and so forth; programs can be created, tested, and debugged without
leaving the application. Program execution can be suspended and resumed
at will or terminated at any time. On-line help is provided.
ProIcon has many extensions beyond the standard version of Icon, including
o function tracing (in addition to procedure tracing)
o an optional termination dump of variables and their values
o functions for manipulating windows, their contents, and the clipboard
o functions for navigating through folders
o functions for determining and setting file signatures
Version 2.0 of ProIcon corresponds to Version 8 of Icon and has all its
features.
New with ProIcon 2.0 is support for external functions that provide access to
HyperCard XCMDs and XFCNs, as well as functions that manipulate Icon data
directly.
ProIcon 2.0 also supports Icon's memory monitoring facility for saving details
of storage allocation and garbage collection in allocation history files. A
separate application provides animated color displays of allocation history
files.
Programs compiled under ProIcon can be given or sold to others; there are
no licensing requirements or royalty fees for such distribution.
For information about ProIcon, contact:
Catspaw, Inc.
P.O. Box 1123
Salida, Colorado 81201-1123
(719) 539-3884
Ralph Griswold / Dept of Computer Science / Univ of Arizona / Tucson, AZ 85721
(602) 621-6609 ralph@cs.arizona.edu uunet!arizona!ralph
From R.J.Hare@edinburgh.ac.uk Mon Dec 24 03:21:01 1990
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA19706; Mon, 24 Dec 90 03:21:01 -0700
Received: from UKACRL.BITNET by Arizona.edu; Mon, 24 Dec 90 03:20 MST
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 0079; Mon,
24 Dec 90 10:20:02 GMT
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 9567; Mon, 24
Dec 90 10:20:02 GMT
Date: 24 Dec 90 10:20:18 gmt
From: R.J.Hare@edinburgh.ac.uk
Subject: system routine
To: icon-group@cs.arizona.edu
Message-Id: <24 Dec 90 10:20:18 gmt 060101@EMAS-A>
Via: UK.AC.ED.EMAS-A; 24 DEC 90 10:20:00 GMT
X-Envelope-To: icon-group@cs.arizona.edu
Hi. I wrote the following short routine to demonstrate (prove) to someone that
the system routine worked (I included the modified prompt as visual evidence
of the proof).
procedure main()
writes(&clock[1:6]," ERCVAX:")
#main loop
while line:=read() do Eif line=="quit" then exit()
else Esystem(line)
write()
writes(&clock[1:6]," ERCVAX:")LL
end
The program seems to work ok in that if I pass a VMS command string to the
program, it all works fine *except* that if I do a set default mumble,
mumble], ie: try to change directories, it fails.
Any ideas why please?
Thanks.
Roger Hare.
From R.J.Hare@edinburgh.ac.uk Mon Dec 24 04:16:07 1990
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA22283; Mon, 24 Dec 90 04:16:07 -0700
Received: from UKACRL.BITNET by Arizona.edu; Mon, 24 Dec 90 04:15 MST
Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 0243; Mon,
24 Dec 90 11:15:13 GMT
Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 9789; Mon, 24
Dec 90 11:15:13 GMT
Date: 24 Dec 90 11:15:34 gmt
From: R.J.Hare@edinburgh.ac.uk
Subject: Last message
To: icon-group@cs.arizona.edu
Message-Id: <24 Dec 90 11:15:34 gmt 060109@EMAS-A>
Via: UK.AC.ED.EMAS-A; 24 DEC 90 11:15:12 GMT
X-Envelope-To: icon-group@cs.arizona.edu
Please ignore my last message - I should have sent it to the Icon project,
not to the Icon group.
Roger Hare.
From mlfarm!ron@hsi.hsi.com Wed Dec 26 07:29:57 1990
Received: from hsi.hsi.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA24245; Wed, 26 Dec 90 07:29:57 -0700
Received: by hsi.hsi.com (5.61+++/1.34)
id AA21170; Wed, 26 Dec 90 09:28:10 -0500
Received: by mlfarm.com (smail2.5)
id AA07340; 23 Dec 90 07:39:17 EST (Sun)
To: icon-group@cs.arizona.edu
Subject: Icon as a teaching language
Message-Id: <9012230739.AA07340@mlfarm.com>
Date: 23 Dec 90 07:39:17 EST (Sun)
From: mlfarm!ron@hsi.hsi.com (Ronald Florence)
With the Christmas vacation upon us and a 12-year old around the
house, I wonder if anyone has had experience with Icon as a first
structured language. My son is adept at vi and gnuplot, and for
homework problems I have occasionally kludged together awk scripts,
which he then modifies as he needs. I suspect some of the more
elegant and terse Icon constructions could be daunting, but the
multiplicity of approaches to a given problem could be fun.
Has anyone tried this? Any wisdom or suggestions?
--
Ronald Florence ron@mlfarm.com
From wgg@cs.washington.edu Wed Dec 26 11:40:25 1990
Received: from june.cs.washington.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA29524; Wed, 26 Dec 90 11:40:25 -0700
Received: by june.cs.washington.edu (5.64/7.0jh)
id AA07710; Wed, 26 Dec 90 10:40:10 -0800
Date: Wed, 26 Dec 90 10:40:10 -0800
From: wgg@cs.washington.edu (William Griswold)
Return-Path: <wgg@cs.washington.edu>
Message-Id: <9012261840.AA07710@june.cs.washington.edu>
To: icon-group@cs.arizona.edu, mlfarm!ron@hsi.hsi.com
Subject: Re: Icon as a teaching language
>From: mlfarm!ron@hsi.hsi.com (Ronald Florence)
>
>With the Christmas vacation upon us and a 12-year old around the
>house, I wonder if anyone has had experience with Icon as a first
>structured language....
Well, I was programming in SNOBOL at this age. The results were fun
but aesthetically disasterous. Certainly Icon would be at least as
fun and perhaps a better language to begin with. If you can get him
playing with some of the more advanced functions, such as map and
random selection (kids eat this stuff up), he'll have a blast.
Actually, giving him something to modify could be very effective.
Small changes in small Icon programs can yield vastly different but
useful results. The Icon books are full of small programs that are easy to
write and modify.
Don't forget numeric calculations as well. Your child may be old enough
to program a sieve for primes (my first program divided by all the numbers
less than or equal to 1/2 the number. It wasn't long before I figured out
I could leave out most of the even numbers....) or some other such program.
Unfortunately Icon isn't interactively interpretive, so you can't
run-as-you-program. I've written a little line-oriented interpreter loop
for Icon, but it changes the syntax and doesn't allow procedures....
Bill Griswold
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Fri Dec 28 09:23:47 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA04048; Fri, 28 Dec 90 09:23:47 -0700
Received: by uwm.edu; id AA29316; Fri, 28 Dec 90 10:23:25 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Fri, 28 Dec 90 09:32:52 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Fri, 28 Dec 1990 09:05 CST
Date: Fri, 28 Dec 1990 09:05 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: TAR
To: icon-group@cs.arizona.edu
Message-Id: <AB97A89CC0200EAF@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
I run Icon V8 under VAX/VMS 5.2. I occasionally come across tar tapes/files.
I know tar is built into unix. But I'll ask anyway,
Has anyone written their own TAR utility in ICON? If not, could someone
mail or post me the spec, both the syntax of the tar utility, and the
data layout.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Fri Dec 28 10:08:21 1990
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA05206; Fri, 28 Dec 90 10:08:21 -0700
Received: by uwm.edu; id AA29925; Fri, 28 Dec 90 11:08:17 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Fri, 28 Dec 90 10:40:20 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Fri, 28 Dec 1990 09:36 CST
Date: Fri, 28 Dec 1990 09:36 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: iconx
To: icon-group@cs.arizona.edu
Message-Id: <AFEE8D5860200EAF@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
I noticed on my postings that some had commented that the
ICONX PROGRAM ...
is unnecessary. This may be partly true under unix. MSDOS needs the ICONX
all the time. Under VMS we have a script called IEXE which converts
ICONX PROG unto a symbol(alias) PROG. This is handy for utilities that
are used very commonly. Under VMS icon paints screens so slow that I
usually use DCL (shell commands) to build the screen or menu, and build icon
filters to manipulate the files underneathe.
Some years ago I ported ICON to a ZS-1 super-minicomputer from Astronautics.
There were certain configuration parameters that were set before building
the software. One or more parameters were concerned with whether icon utilities
needed iconx explicitly, or if it rolled a little executable into the icode.
However, since main(){printf("hello\n");} generated about 200k of executable.
The icode of most of the utilities I wrote was typically 2-4k, and the disks
were pretty full, it was smarter there to keep the icode separate, so iconx
would be required. That was in the Icon 7.0 days, and maybe Icon 8 is much
different under unix.
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
From mlfarm!ron@hsi.hsi.com Sat Dec 29 09:47:04 1990
Received: from hsi.hsi.com by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA08896; Sat, 29 Dec 90 09:47:04 -0700
Received: by hsi.hsi.com (5.61+++/1.34)
id AA23539; Sat, 29 Dec 90 11:45:16 -0500
Received: by mlfarm.com (smail2.5)
id AA14370; 29 Dec 90 11:43:14 EST (Sat)
To: icon-group@cs.arizona.edu
In-Reply-To: Chris Tenaglia - 257-8765's message of Fri Dec 28 09:36 CST
Subject: iconx
Message-Id: <9012291143.AA14370@mlfarm.com>
Date: 29 Dec 90 11:43:14 EST (Sat)
From: mlfarm!ron@hsi.hsi.com (Ronald Florence)
Chris Tenaglia - 257-8765 writes:
> I noticed on my postings that some had commented that the
>
> ICONX PROGRAM ...
>
> is unnecessary.
What I wrote was that the `ICONX' is system-specific, and that the
users of systems which do not have direct execution (VMS, ms-dos) will
know to use it. Because commands are case-sensitive, `ICONX PROGRAM'
won't work on most unix systems.
> The icode of most of the utilities I wrote was typically 2-4k, and the disks
> were pretty full, it was smarter there to keep the icode separate, so iconx
> would be required.
It would be interesting to compare the size of the compiled code on
various systems. The canonical hello.icn compiles to 6941 bytes here
(Xenix 386, direct execution). Is it much smaller on VMS or ms-dos
systems without direct execution?
--
Ronald Florence ron@mlfarm.com
From fps!mis.mcw.edu!mis.mcw.edu!TENAGLIA@uwm.edu Tue Jan 1 09:42:36 1991
Received: from uwm.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA00177; Tue, 1 Jan 91 09:42:36 -0700
Received: by uwm.edu; id AA01354; Tue, 1 Jan 91 08:34:39 -0600
Received: from mis.mcw.edu by fps.mcw.edu (DECUS UUCP ///1.2a/2.5/);
Tue, 1 Jan 91 08:01:24 CDT
Received: by mis.mcw.edu with UUCP/PMDF (DECUS UUCP);
Tue, 1 Jan 1991 07:32 CST
Date: Tue, 1 Jan 1991 07:31 CST
From: Chris Tenaglia - 257-8765 <TENAGLIA@mis.mcw.edu>
Subject: Happy New Year ! Black Jack Game.
To: icon-group@cs.arizona.edu
Message-Id: <C3284CA4006019D9@mis.mcw.edu>
X-Organization: Medical College of Wisconsin MIS Department (Milwaukee, WI)
X-Envelope-To: icon-group@cs.arizona.edu
X-Vms-To: IN%"icon-group@cs.arizona.edu"
Happy New Year! After considering all the good advice on the draw poker game
I kloojed together a simple version of black jack. It's about 291 lines.
The shuffling on the draw poker game also wasn't very good, so this game
uses the technique in the IPL which I think is more correct anyway. Enjoy!
Yours truly,
Chris Tenaglia (System Manager) | Medical College of Wisconsin
8701 W. Watertown Plank Rd. | Milwaukee, WI 53226
(414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia
#########################################################
# #
# BJ.ICN 12/19/90 BY TENAGLIA #
# #
# SIMPLE BUT FUN BLACK JACK GAME. WORKS ON ANSI SCREEN. #
# USAGE : iconx bj [starting credits] #
# #
#########################################################
global deck, message, lookup,
user_money, host_money,
user_hand, host_hand
procedure main(param)
user_money := integer(param[1]) | 3 ; host_money := user_money
write(screen("cls")," ",screen("top"),screen("hinv"),
"BLACK JACK",screen("norm"))
write(" ",screen("bot"),screen("hinv"),
"BLACK JACK",screen("norm"))
bonus := 0
repeat
{
if not any('y',(map(input(at(1,4) || screen("under") ||
"Want to play? y/n :"|| screen("norm") ||
screen("eeol")))[1])) then break
writes(at(1,4),screen("eeos"))
display_score()
deck := shuffle()
message := ""
user_hand := [] ; host_hand := []
put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
user_points := first(host_hand[1])
if user_points > 21 then
{
writes(at(1,14),user_points," points. You went over. You loose.")
user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
display_score()
next
}
display_host(2)
host_points := second(user_points)
if host_points > 21 then
{
writes(at(50,23),host_points," points. ",&host," went over.")
writes(at(1,14),screen("hiblink"),"You win.",screen("norm"))
host_money -:= 1 ; user_money +:= 1 + bonus ; bonus := 0
display_score()
next
}
if host_points = user_points then
{
writes(at(1,23),screen("hiblink"),"It's a draw at ",user_points,
". The ANTY goes to bonus.",screen("norm"))
bonus +:= 2 ; host_money -:= 1 ; user_money -:= 1
display_score()
next
}
writes(at(20,13),user_points," points for user.")
writes(at(1,15),host_points," points for ",&host)
if user_points < host_points then
{
write(at(1,23),screen("hiblink"),&host," wins.",
screen("norm"),screen("eeol"))
user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
display_score()
next
} else {
writes(at(1,13),screen("hiblink"),"You win.",screen("norm"),screen("eeol"))
user_money +:= 1 + bonus ; host_money -:= 1 ; bonus := 0
display_score()
next
}
}
write(screen("clear"))
end
#
# THIS PROCEDURE ALLOWS THE USER TO PLAY AND TAKE HITS
#
procedure first(host_card)
display_user()
display_host(1)
points := value(user_hand) # just in case
writes(at(1,10),"(",points,") ")
repeat
if any('hy',map(input(at(1,23) || "Hit ? y/n :" || screen("eeol")))) then
{
put(user_hand,pop(deck))
display_user()
if (points := value(user_hand)) > 21 then return points
writes(at(1,10),"(",points,") ")
} else break
(points > 0) | (points := value(user_hand))
writes(at(1,10),"(",points,") ")
write(at(60,12),"You stay with ",points)
return points
end
#
# THIS SECOND PROCEDURE IS THE HOST PLAYING AGAINST THE USER
#
procedure second(ceiling)
static limits
initial limits := [14,14,15,15,19,16,17,18]
stop_at := ?limits ; points := 0
until (points := value(host_hand)) > stop_at do
{
if points > ceiling then return points
writes(at(1,20),"(",points,") ")
write(at(1,23),screen("eeol"),&host," will take a hit.",screen("eeol"))
put(host_hand,pop(deck))
display_host(2)
}
(points > 0) | (points := value(host_hand))
writes(at(1,20),"(",points,") ")
return points
end
#
# THIS ROUTINE DISPLAYS THE CURRENT SCORE
#
procedure display_score()
writes(screen("nocursor"))
writes(screen("dim"),at(1,8),"Credits",screen("norm"))
writes(screen("high"),at(1,9),right(user_money,7),screen("norm"))
writes(screen("dim"),at(1,18),"Credits",screen("norm"))
writes(screen("high"),at(1,19),right(host_money,7),screen("norm"))
end
#
# THIS PROCEDURE EVALUATES THE POINTS OF A HAND. IT TRIES TO MAKE THEM
# AS HIGH AS POSSIBLE WITHOUT GOING OVER 21.
#
procedure value(sample)
hand := copy(sample)
possible := []
repeat
{
sum := 0
every card := !hand do sum +:= lookup[card[1]]
put(possible,sum)
if Aces(hand) == "none" then break else
every i := 1 to *hand do if hand[i][1] == "A" then hand[i][1] := "a"
}
every score := !possible do
if score <= 21 then return score
return possible[1]
end
#
# ARE THERE ANY 11 POINT ACES LEFT IN HAND
#
procedure Aces(cards)
every look := !cards do if look[1] == "A" then return "some"
return "none"
end
#
# THIS ROUTINE DISPLAYS THE USER HAND AND STATUS
#
procedure display_user()
writes(screen("nocursor"),at(4,7),screen("hinv"),"USER",screen("norm"))
x := 10 ; y := 5
every card := !user_hand do
{
display(card,x,y)
x +:= 7
}
end
#
# THIS ROUTINE DISPLAYS THE HOST HAND AND STATUS
#
procedure display_host(flag)
writes(screen("nocursor"),at(1,17),screen("hinv"),&host,screen("norm"))
x := 10 ; y := 15 ; /flag := 0
every card := !host_hand do
{
if (flag=1) & (x=10) then card := "XX"
display(card,x,y)
x +:= 7
}
end
#
# THIS ROUTINE DISPLAYS A GIVEN CARD AT A GIVEN X,Y SCREEN LOCATION
#
procedure display(card,x,y)
all := [] ; j := y
if find(card[2],"CS") then card := screen("hinv") || card || screen("norm")
shape := [at(x,(j+:=1)) || screen("gchar") || "lqqqqqqqk"]
put(shape,at(x,(j+:=1)) || "x " || card || " x")
put(shape,at(x,(j+:=1)) || "x x")
put(shape,at(x,(j+:=1)) || "x x")
put(shape,at(x,(j+:=1)) || "x x")
put(shape,at(x,(j+:=1)) || "x " || card || " x")
put(shape,at(x,(j+:=1)) || "mqqqqqqqj" || screen("nchar"))
put(all,shape)
x +:= 14
while shape := pop(all) do every writes(!shape)
end
#
# THIS ROUTINE SHUFFLES THE CARD DECK
#
procedure shuffle()
static faces, suits
local cards, i
initial {
&random := map(&clock,":","7") # initial on multiple shuffles
faces := ["2","3","4","5","6","7","8","9","T","J","Q","K","A"]
suits := ["D","H","C","S"]
lookup := table(0)
every i := 2 to 9 do insert(lookup,string(i),i)
insert(lookup,"T",10)
insert(lookup,"J",10)
insert(lookup,"Q",10)
insert(lookup,"K",10)
insert(lookup,"A",11)
insert(lookup,"a",1)
}
cards := []
every put(cards,!faces || !suits)
every i := *cards to 2 by -1 do cards[?i] :=: cards[i]
return cards
end
#
# THIS ROUTINE PARSES A STRING WITH RESPECT TO SOME DELIMITER
#
procedure parse(line,delims)
static chars
chars := &cset -- delims
tokens := []
line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
return tokens
end
#
# THIS ROUTINE PROMPTS FOR INPUT AND RETURNS A STRING
#
procedure input(prompt)
writes(screen("cursor"),prompt)
return read()
end
#
# THIS ROUTINE SETS THE VIDEO OUTPUT ATTRIBUTES FOR VT102 OR LATER
# COMPATIBLE TERMINALS.
#
procedure screen(attr)
case attr of
{
"cls" : return "\e[2J\e[H" # CLEAR SCREEN
"clear": return "\e[2J\e[H" # CLEAR SCREEN
"top" : return "\e#3" # UPPER HALF CHARACTERS
"bot" : return "\e#4" # LOWER HALF CHARACTERS
"fat" : return "\e#6" # SINGLE HEIGHT FAT LETTERS
"thin" : return "\e#5" # NORMAL SIZED CHARACTERS
"hinv" : return "\e[1;7m" # HIGH INTENSITY & INVERSE
"norm" : return "\e[m" # RESTORE NORMAL VIDEO ATTRIBUTES
"dim" : return "\e[2m" # LOW INTENSITY VIDEO
"blink": return "\e[5m" # VIDEO BLINKING ATTRIBUTE
"hiblink": return "\e[1;5m" # HIGH INTENSITY BLINKING
"under": return "\e[4m" # VIDEO UNDERLINING ATTRIBUTE
"high" : return "\e[1m" # VIDEO HIGH INTENSITY ATTRIBUTE
"inv" : return "\e[7m" # VIDEO INVERSE ATTRIBUTE
"eeol" : return "\e[K" # ERASE TO END OF LINE
"esol" : return "\e[1K" # ERASE TO START OF LINE
"eeos" : return "\e[J" # ERASE TO END OF SCREEN
"gchar": return "\e(0" # TURN ON ANSI GRAPHICS MODE
"nchar": return "\e(B" # TURN OFF ANSI GRAPHICS MODE
"light": return "\e[?5h" # LIGHT COLORED SCREEN
"dark" : return "\e[?5l" # DARK COLORED SCREEN
"80" : return "\e[?3l" # 80 COLUMNS ON SCREEN
"132" : return "\e[?3h" # 132 COLUMNS ON SCREEN
"smooth": return "\e[?4h" # SMOOTH SCREEN SCROLLING
"jump" : return "\e[?4l" # JUMP SCREEN SCROLLING
"cursor": return "\e[?25h" # MAKE SURE CURSOR IS VISIBLE
"nocursor": return "\e[?25l" # HIDE THE CURSOR
default: return "("||attr||")"
}
end
#
# THIS ROUTINE SETS THE CURSOR TO A GIVEN X (COL) Y(ROW) SCREEN LOCATION
#
procedure at(x,y)
return "\e[" || y || ";" || x || "f"
end
From @um.cc.umich.edu:Paul_Abrahams@Wayne-MTS Tue Jan 1 20:06:36 1991
Received: from umich.edu by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA12591; Tue, 1 Jan 91 20:06:36 -0700
Received: from um.cc.umich.edu by umich.edu (5.61/1123-1.0)
id AA04966; Tue, 1 Jan 91 22:06:27 -0500
Received: from Wayne-MTS by um.cc.umich.edu via MTS-Net; Tue, 1 Jan 91 22:03:41 EST
Date: Tue, 1 Jan 91 16:34:36 EST
From: Paul_Abrahams%Wayne-MTS@um.cc.umich.edu
To: icon-group@cs.arizona.edu
Message-Id: <281696@Wayne-MTS>
Subject: Message conventions
This isn't exactly an Icon question, but.....
I've noticed that in many of the postings to icon-group, the messages have
excerpts from previous messages preceded by "> ". Could anyone let me know
what software you're using to get this effect, and how you're using it?
Thanks.
Paul Abrahams
abrahams%wayne-mts@um.cc.umich.edu
From icon-group-request@arizona.edu Tue Jan 1 21:52:02 1991
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14616; Tue, 1 Jan 91 21:52:02 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 1 Jan 91 21:51 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA29802; Tue, 1 Jan 91 20:44:27
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 1 Jan 91 21:51 MST
Date: 2 Jan 91 02:56:21 GMT
From: netnews.upenn.edu!msuinfo!midway!quads.uchicago.edu!goer@rutgers.edu
Subject: bj, part 3 of 3
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <DEC4BED6C699400483@Arizona.edu>
Message-Id: <1991Jan2.025621.21511@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <1991Jan2.025428.21379@midway.uchicago.edu>
stty: Operation not supported on socket
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is bj.03 (part 3 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file itlibdos.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping itlibdos.icn'
else
echo 'x - continuing file itlibdos.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'itlibdos.icn' &&
X range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
X er("igoto",colline || " out of range " || (\range|""),9)
X }
X
X # Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
X increment := -1
X outstr := ""
X
X cm ? {
X while outstr ||:= tab(find("%")) do {
X tab(match("%"))
X chr := move(1)
X if case chr of {
X "." : outstr ||:= char(line + increment)
X "+" : outstr ||:= char(line + ord(move(1)) + increment)
X "d" : {
X str := string(line + increment)
X outstr ||:= right(str, integer(tab(any('23'))), "0") | str
X }
X }
X then line :=: col
X else {
X case chr of {
X "n" : line := ixor(line,96) & col := ixor(col,96)
X "i" : increment := 0
X "r" : line :=: col
X "%" : outstr ||:= "%"
X "B" : line := ior(ishift(line / 10, 4), line % 10)
X ">" : {
X x := move(1); y := move(1)
X line > ord(x) & line +:= ord(y)
X &null
X }
X } | er("goto","bad termcap entry",5)
X }
X }
X return outstr || tab(0)
X }
X
Xend
X
X
X
Xprocedure iputs(cp, affcnt)
X
X # Writes cp to the screen. Use this instead of writes() for
X # compatibility with the Unix version (which will need to send
X # null padding in some cases). Iputs() also does a useful type
X # check.
X
X static num_chars
X initial num_chars := &digits ++ '.'
X
X type(cp) == "string" |
X er("iputs","you can't iputs() a non-string value!",10)
X
X cp ? {
X if tab(many(num_chars)) & ="*" then
X stop("iputs: MS-DOS termcap files shouldn't specify padding.")
X writes(tab(0))
X }
X
X return
X
Xend
SHAR_EOF
echo 'File itlibdos.icn is complete' &&
true || echo 'restore of itlibdos.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= termcap.dos ==============
if test -f 'termcap.dos' -a X"$1" != X"-c"; then
echo 'x - skipping termcap.dos (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting termcap.dos (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'termcap.dos' &&
Xansi|color|ansi-color|ibm|ibmpc|ANSI.SYS color:\
X :co#80:li#24:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[H\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[0;44m:\
X :us=\E[1;31;44m:ue=\E[0;44m:\
X :mb=\E[5m:md=\E[1m:me=\E[0;44m:
Xmono|ansi-mono|ANSI.SYS:\
X :co#80:li#24:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[H\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :so=\E[1m:se=\E[m:us=\E[4m:ue=\E[m:\
X :mb=\E[5m:md=\E[1m:me=\E[m:
Xnnansi-mono|NNANSI.SYS:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:cd=\E[J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :so=\E[1m:se=\E[2m:\
X :us=\E[4m:ue=\E[24m:\
X :mb=\E[5m:md=\E[1m:mh=\E[2m:mr=\E[7m:me=\E[m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnnansi|nnansi-color|NNANSI.SYS color:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:cd=\E[J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[2;37m:\
X :us=\E[4m:ue=\E[24m:\
X :mb=\E[5m:md=\E[1m:mh=\E[2m:mr=\E[7m:me=\E[0;44m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnansi-mono|zansi-mono|N/ZANSI.SYS:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0m:te=\E[0m:\
X :so=\E[1;35m:se=\E[0m:\
X :us=\E[1;31m:ue=\E[0m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
Xnansi|zansi|nansi-color|zansi-color|N/ZANSI.SYS color:\
X :co#80:li#25:bs:pt:bl=^G:le=^H:do=^J:\
X :cl=\E[2J:ce=\E[K:\
X :ho=\E[H:cm=\E[%i%d;%dH:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :ti=\E[0;44m:te=\E[0m:\
X :so=\E[1;35;44m:se=\E[0;44m:\
X :us=\E[1;31;44m:ue=\E[0;44m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[0;44m:\
X :al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:
XAX|ANSI X3.64|full ANSI X3.64 (1977) standard:\
X :co#80:li#24:bs:pt:am:mi:bl=^G:le=^H:\
X :cl=\E[2J:ce=\E[K:cd=\E[J:\
X :ho=\E[H:cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:\
X :up=\E[A:do=\E[B:le=\E[C:ri=\E[D:nd=\E[C:\
X :UP=\E[%dA:DO=\E[%dB:LE=\E[%dC:RI=\E[%dD:\
X :so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\
X :mb=\E[5m:md=\E[1m:mr=\E[7m:me=\E[m:as=^N:ae=^O:\
X :ku=\E[A:kd=\E[B:kl=\E[C:kr=\E[D:kb=^H:\
X :kn#4:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\
X :im=\E[4h:ei=\E[4l:al=\E[L:dl=\E[M:ic=\E[@:dc=\E[P:sf=\ED:sr=\EM:
SHAR_EOF
true || echo 'restore of termcap.dos failed'
rm -f _shar_wnt_.tmp
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
echo 'x - skipping README (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
XThis package is a simple UNIX port of Chris Tenaglia's blackjack
Xgame for full ANSI terminals. Because of the structure of the
Xoriginal program (read: because I was lazy) this port won't work
Xwith magic cookie terminals. It works best on terminals that have
Xboldface, reverse, dim, and blink modes. If any of these are mis-
Xsing, the appearance of the game will be somewhat altered. Ter-
Xminals must be at least 24x80.
X
XTo make for UNIX, just copy Makefile.dist to Makefile and type
X"make." If all goes well, and you have root priviledges, su to
Xroot and type "make install." You'll have to edit the makefile
Xto reflect local file structures and conventions.
X
XIncluded with this distribution is also a DOS implementation of
Xthe itlib routines and a termcap file. To run this program on a
XDOS system, first compile using
X
X icont -o bj bj.icn itlibdos.icn
X
XRead the directions in the file itlibdos.icn for instructions as
Xto how to install a termcap file. NOTE WELL: THE TERMCAP FOR
XDOS IS NOT TERRIBLY GOOD, AND IN ORDER TO GET IT TO WORK, YOU
XWILL CERTAINLY NEED TO FIX IT UP. I don't use DOS much, and will
Xjust have to hope that some any revisions that get made will make
Xtheir way back to me.
X
XNaturally, UNIX users can erase all the DOS files ("rm *dos*").
XDOS users can erase itlibdos.icn and Makefile.dist. If anything
Xgoes awry, or if a standard terminal such as a VT-XXX or and
XANSI fails to run bj, please let me know. I expect that older
Xterminals without a full assortment of modes - if they run it
Xat all - will not do so very smartly.
X
XEnjoy Chris's game, and have a good 1991!
X
X-Richard Goerwitz (goer@sophist.uchicago.edu)
SHAR_EOF
true || echo 'restore of README failed'
rm -f _shar_wnt_.tmp
fi
# ============= Makefile.dist ==============
if test -f 'Makefile.dist' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile.dist (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Makefile.dist (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.dist' &&
X# Don't change this unless you know what you are doing :-).
XPROGNAME = bj
X
X# Please edit these to reflect your local file structure & conventions.
XDESTDIR = /usr/local/bin
XOWNER = bin
XGROUP = bin
X
X# Please don't change these.
XSRC = $(PROGNAME).icn itlib.icn
X
X# I hope you won't have to use this.
X# DEBUGFLAG = -t
X
X$(PROGNAME): $(SRC)
X /usr/local/bin/icont $(DEBUGFLAG) -o $(PROGNAME) $(SRC)
X
X# Pessimistic assumptions regarding the environment (in particular,
X# I don't assume you have the BSD "install" shell script).
Xinstall: $(PROGNAME)
X @sh -c "test -d $(DESTDIR) || (mkdir $(DESTDIR) && chmod 755 $(DESTDIR))"
X cp $(PROGNAME) $(DESTDIR)/
X chgrp $(GROUP) $(DESTDIR)/$(PROGNAME)
X chown $(OWNER) $(DESTDIR)/$(PROGNAME)
X @echo "\nInstallation done.\n"
X
SHAR_EOF
true || echo 'restore of Makefile.dist failed'
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo You have unpacked the last part
exit 0
From icon-group-request@arizona.edu Tue Jan 1 21:52:26 1991
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14625; Tue, 1 Jan 91 21:52:26 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 1 Jan 91 21:51 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA29795; Tue, 1 Jan 91 20:44:06
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 1 Jan 91 21:51 MST
Date: 2 Jan 91 02:55:23 GMT
From: netnews.upenn.edu!msuinfo!midway!quads.uchicago.edu!goer@rutgers.edu
Subject: bj, part 2 of 3
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <DEC4AF716E39400484@Arizona.edu>
Message-Id: <1991Jan2.025523.21456@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
References: <1991Jan2.025428.21379@midway.uchicago.edu>
stty: Operation not supported on socket
---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is bj.02 (part 2 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file itlib.icn continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping itlib.icn'
else
echo 'x - continuing file itlib.icn'
sed 's/^X//' << 'SHAR_EOF' >> 'itlib.icn' &&
X (tab(find(":")+1), tab(0)))
X return entry
X }
X else {
X \line := &null # must precede the next line
X entry ||:= trim(trim(tab(0),'\\'),':')
X }
X }
X }
X }
X }
X
X close(f)
X er("getentry","can't find and/or process your termcap entry",3)
X
Xend
X
X
X
Xprocedure read_file(f)
X
X # Suspends all non #-initial lines in the file f.
X # Removes leading tabs and spaces from lines before suspending
X # them.
X
X local line
X
X \f | er("read_tcap_file","no valid termcap file found",3)
X while line := read(f) do {
X match("#",line) & next
X line ?:= (tab(many('\t ')) | &null, tab(0))
X suspend line
X }
X
X fail
X
Xend
X
X
X
Xprocedure maketc_table(entry)
X
X # Maketc_table(s) (where s is a valid termcap entry for some
X # terminal-type): Returns a table in which the keys are termcap
X # capability designators, and the values are the entries in
X # "entry" for those designators.
X
X local k, v
X
X /entry & er("maketc_table","no entry given",8)
X if entry[-1] ~== ":" then entry ||:= ":"
X
X /tc_table := table()
X
X entry ? {
X
X tab(find(":")+1) # tab past initial (name) field
X
X while tab((find(":")+1) \ 1) ? {
X &subject == "" & next
X if k := 1(move(2), ="=")
X then tc_table[k] := Decode(tab(find(":")))
X else if k := 1(move(2), ="#")
X then tc_table[k] := integer(tab(find(":")))
X else if k := 1(tab(find(":")), pos(-1))
X then tc_table[k] := true()
X else er("maketc_table", "your termcap file has a bad entry",3)
X }
X }
X
X return tc_table
X
Xend
X
X
X
Xprocedure getval(id)
X
X /tc_table := maketc_table(getentry(getname())) |
X er("getval","can't make a table for your terminal",4)
X
X return \tc_table[id] | fail
X # er("getval","the current terminal doesn't support "||id,7)
X
Xend
X
X
X
Xprocedure Decode(s)
X
X # Does things like turn ^ plus a letter into a genuine control
X # character.
X
X new_s := ""
X
X s ? {
X
X while new_s ||:= tab(upto('\\^')) do {
X chr := move(1)
X if chr == "\\" then {
X new_s ||:= {
X case chr2 := move(1) of {
X "\\" : "\\"
X "^" : "^"
X "E" : "\e"
X "b" : "\b"
X "f" : "\f"
X "n" : "\n"
X "r" : "\r"
X "t" : "\t"
X default : {
X if any(&digits,chr2) then {
X char(integer("8r"||chr2||move(2 to 0 by -1))) |
X er("Decode","bad termcap entry",3)
X }
X else chr2
X }
X }
X }
X }
X else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
X }
X new_s ||:= tab(0)
X }
X
X return new_s
X
Xend
X
X
X
Xprocedure igoto(cm,col,line)
X
X local colline, range, increment, str, outstr, chr, x, y
X
X if col > (tc_table["co"]) | line > (tc_table["li"]) then {
X colline := string(\col) || "," || string(\line) | string(\col|line)
X range := "(" || tc_table["co"]-1 || "," || tc_table["li"]-1 || ")"
X er("igoto",colline || " out of range " || (\range|""),9)
X }
X
X # Use the Iconish 1;1 upper left corner & not the C-ish 0 offsets
X increment := -1
X outstr := ""
X
X cm ? {
X while outstr ||:= tab(find("%")) do {
X tab(match("%"))
X chr := move(1)
X if case chr of {
X "." : outstr ||:= char(line + increment)
X "+" : outstr ||:= char(line + ord(move(1)) + increment)
X "d" : {
X str := string(line + increment)
X outstr ||:= right(str, integer(tab(any('23'))), "0") | str
X }
X }
X then line :=: col
X else {
X case chr of {
X "n" : line := ixor(line,96) & col := ixor(col,96)
X "i" : increment := 0
X "r" : line :=: col
X "%" : outstr ||:= "%"
X "B" : line := ior(ishift(line / 10, 4), line % 10)
X ">" : {
X x := move(1); y := move(1)
X line > ord(x) & line +:= ord(y)
X &null
X }
X } | er("goto","bad termcap entry",5)
X }
X }
X return outstr || tab(0)
X }
X
Xend
X
X
X
Xprocedure iputs(cp, affcnt)
X
X local baud_rates, char_rates, i, delay, PC
X static num_chars, char_times
X # global tty_speed
X
X initial {
X num_chars := &digits ++ '.'
X char_times := table()
X # Baud rates in decimal, not octal (as in termio.h)
X baud_rates := [0,7,8,9,10,11,12,13,14,15]
X char_rates := [0,333,166,83,55,41,20,10,10,10]
X every i := 1 to *baud_rates do {
X char_times[baud_rates[i]] := char_rates[i]
X }
X }
X
X type(cp) == "string" |
X er("iputs","you can't iputs() a non-string value!",10)
X
X cp ? {
X delay := tab(many(num_chars))
X if ="*" then {
X delay *:= \affcnt |
X er("iputs","affected line count missing",6)
X }
X writes(tab(0))
X }
X
X if (\delay, tty_speed ~= 0) then {
X PC := tc_table["pc"] | "\000"
X char_time := char_times[tty_speed] | (return "speed error")
X delay := (delay * char_time) + (char_time / 2)
X every 1 to delay by 10
X do writes(PC)
X }
X
X return
X
Xend
X
X
X
Xprocedure getspeed()
X
X local stty_g, stty_output, c_cflag, o_speed
X
X stty_g := open("/bin/stty -g 2>&1","pr") |
X er("getspeed","Can't access your stty command.",4)
X stty_output := !stty_g
X close(stty_g)
X
X \stty_output ? {
X # tab to the third field of the output of the stty -g cmd
X tab(find(":")+1) & tab(find(":")+1) &
X c_cflag := integer("16r"||tab(find(":")))
X } | er("getspeed","Unable to unwind your stty -g output.",4)
X
X o_speed := iand(15,c_cflag)
X return o_speed
X
Xend
SHAR_EOF
echo 'File itlib.icn is complete' &&
true || echo 'restore of itlib.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= itlibdos.icn ==============
if test -f 'itlibdos.icn' -a X"$1" != X"-c"; then
echo 'x - skipping itlibdos.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting itlibdos.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'itlibdos.icn' &&
X##########################################################################
X#
X# Name: itlibdos.icn
X#
X# Title: Icon termlib-type tools (MS-DOS version)
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.12
X#
X###########################################################################
X#
X# I place this and future versions of itlibdos in the public domain - RLG
X#
X###########################################################################
X#
X# The following library represents a series of rough functional
X# equivalents to the standard Unix low-level termcap routines. They
X# are not meant as exact termlib clones. Nor are they enhanced to
X# take care of magic cookie terminals, terminals that use \D in their
X# termcap entries, or, in short, anything I felt would not affect my
X# normal, day-to-day work with ANSI and vt100 terminals.
X#
X# Requires: An MS-DOS platform & co-expressions. The MS-DOS version
X# is a port of the Unix version. Software you write for this library
X# can be made to run under Unix simply by substituting the Unix ver-
X# sion of this library. See below for additional notes on how to use
X# this MS-DOS port.
X#
X# setname(term)
X# Use only if you wish to initialize itermlib for a terminal
X# other than what your current environment specifies. "Term" is the
X# name of the termcap entry to use. Normally this initialization is
X# done automatically, and need not concern the user.
X#
X# getval(id)
X# Works something like tgetnum, tgetflag, and tgetstr. In the
X# spirit of Icon, all three have been collapsed into one routine.
X# Integer valued caps are returned as integers, strings as strings,
X# and flags as records (if a flag is set, then type(flag) will return
X# "true"). Absence of a given capability is signalled by procedure
X# failure.
X#
X# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
X# Analogous to tgoto. "Cm" is the cursor movement command for
X# the current terminal, as obtained via getval("cm"). Igoto()
X# returns a string which, when output via iputs, will cause the
X# cursor to move to column "destcol" and line "destline." Column and
X# line are always calculated using a *one* offset. This is far more
X# Iconish than the normal zero offset used by tgoto. If you want to
X# go to the first square on your screen, then include in your program
X# "iputs(igoto(getval("cm"),1,1))."
X#
X# iputs(cp,affcnt)
X# Equivalent to tputs. "Cp" is a string obtained via getval(),
X# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
X# count of affected lines. It is only relevant for terminals which
X# specify proportional (starred) delays in their termcap entries.
X#
X# Notes on the MS-DOS version:
X# There are two basic reasons for using the I/O routines
X# contained in this package. First, by using a set of generalized
X# routines, your code will become much more readable. Secondly, by
X# using a high level interface, you can avoid the cardinal
X# programming error of hard coding things like screen length and
X# escape codes into your programs.
X# To use this collection of programs, you must do two things.
X# First, you must add the line "device=ansi.sys" (or the name of some
X# other driver, like zansi.sys, nansi.sys, or nnansi.sys [=new
X# nansi.sys]) to your config.sys file. Secondly, you must add two
X# lines to your autoexec.bat file: 1) "set TERM=ansi-mono" and 2)
X# "set TERMCAP=\location\termcap." The purpose of setting the TERM
X# variable is to tell this program what driver you are using. If you
X# have a color system, use "ansi-color" instead of "ansi-mono," and
X# if you are using nansi or zansi instead of vanilla ansi, use one of
X# these names instead of the "ansi" (e.g. "zansi-mono"). The purpose
X# of setting TERMCAP is to make it possible to determine where the
X# termcap file is located. The termcap file (which should have been
X# packed with this library as termcap.dos) is a short database of all
X# the escape sequences used by the various terminal drivers. Set
X# TERMCAP so that it reflects the location of this file (which should
X# be renamed as termcap, for the sake of consistency with the Unix
X# version). Naturally, you must change "\location\" above to reflect
X# the correct path on your system.
X# Although I make no pretense here of providing here a complete
X# introduction to the format of the termcap database file, it will be
X# useful, I think, to explain a few basic facts about how to use this
X# program in conjunction with it. If, say, you want to clear the
X# screen, add the line,
X#
X# iputs(getval("cl"))
X#
X# to your program. The function iputs() outputs screen control
X# sequences. Getval retrieves a specific sequence from the termcap
X# file. The string "cl" is the symbol used in the termcap file to
X# mark the code used to clear the screen. By executing the
X# expression "iputs(getval("cl"))," you are 1) looking up the "cl"
X# (clear) code in the termcap database entry for your terminal, and
X# the 2) outputting that sequence to the screen.
X# Some other useful termcap symbols are "ce" (clear to end of
X# line), "ho" (go to the top left square on the screen), "so" (begin
X# standout mode), and "se" (end standout mode). To output a
X# boldfaced string, str, to the screen, you would write -
X#
X# iputs(getval("so"))
X# writes(str)
X# iputs(getval("se"))
X#
X# You could write "iputs(getval("so") || str || getval("se")), but
X# this would only work for DOS. Some Unix terminals require padding,
X# and iputs() handles them specially. Normally you should not worry
X# about Unix quirks under DOS. It is in general wise, though, to
X# separate out screen control sequences, and output them via iputs().
X# It is also heartily to be recommended that MS-DOS programmers
X# try not to assume that everyone will be using a 25-line screen.
X# Some terminals are 24-line. Some 43. Some have variable window
X# sizes. If you want to put a status line on, say, the 2nd-to-last
X# line of the screen, then determine what that line is by executing
X# "getval("li")." The termcap database holds not only string-valued
X# sequences, but numeric ones as well. The value of "li" tells you
X# how many lines the terminal has (compare "co," which will tell you
X# how many columns). To go to the beginning of the second-to-last
X# line on the screen, type in:
X#
X# iputs(igoto(getval("cm"), 1, getval("li")-1))
X#
X# The "cm" capability is a special capability, and needs to be output
X# via igoto(cm,x,y), where cm is the sequence telling your computer
X# to move the cursor to a specified spot, x is the column, and y is
X# the row. The expression "getval("li")-1" will return the number of
X# the second-to-last line on your screen.
X#
X##########################################################################
X#
X# Requires: MS-DOS, coexpressions
X#
X# See also: iscreen.icn (a set of companion utilities)
X#
X##########################################################################
X
X
Xglobal tc_table
Xrecord true()
X
X
Xprocedure check_features()
X
X local in_params, line
X
X initial {
X find("ms-dos",map(&features)) |
X er("check_features","MS-DOS system required",1)
X find("o-expres",&features) |
X er("check_features","co-expressions not implemented - &$#!",1)
X }
X
X return
X
Xend
X
X
X
Xprocedure setname(name)
X
X # Sets current terminal type to "name" and builds a new termcap
X # capability database (residing in tc_table). Fails if unable to
X # find a termcap entry for terminal type "name." If you want it
X # to terminate with an error message under these circumstances,
X # comment out "| fail" below, and uncomment the er() line.
X
X #tc_table is global
X
X check_features()
X
X tc_table := maketc_table(getentry(name)) | fail
X # er("setname","no termcap entry found for "||name,3)
X return
X
Xend
X
X
X
Xprocedure getname()
X
X # Getname() first checks to be sure we're running under DOS, and,
X # if so, tries to figure out what the current terminal type is,
X # checking the value of the environment variable TERM, and if this
X # is unsuccessful, defaulting to "mono."
X
X local term, tset_output
X
X check_features()
X term := getenv("TERM") | "mono"
X
X return \term |
X er("getname","can't seem to determine your terminal type",1)
X
Xend
X
X
X
Xprocedure er(func,msg,errnum)
X
X # short error processing utility
X write(&errout,func,": ",msg)
X exit(errnum)
X
Xend
X
X
X
Xprocedure getentry(name, termcap_string)
X
X # "Name" designates the current terminal type. Getentry() scans
X # the current environment for the variable TERMCAP. If the
X # TERMCAP string represents a termcap entry for a terminal of type
X # "name," then getentry() returns the TERMCAP string. Otherwise,
X # getentry() will check to see if TERMCAP is a file name. If so,
X # getentry() will scan that file for an entry corresponding to
X # "name." If the TERMCAP string does not designate a filename,
X # getentry() will look through ./termcap for the correct entry.
X # Whatever the input file, if an entry for terminal "name" is
X # found, getentry() returns that entry. Otherwise, getentry()
X # fails.
X
X local f, getline, line, nm, ent1, ent2
X
X /termcap_string := getenv("TERMCAP")
X
X if \termcap_string ? (not match("\\"), pos(0) | tab(find("|")+1), =name)
X then return termcap_string
X else {
X
X # The logic here probably isn't clear. The idea is to try to use
X # the termcap environment variable successively as 1) a termcap en-
X # try and then 2) as a termcap file. If neither works, 3) go to
X # the ./termcap file. The else clause here does 2 and, if ne-
X # cessary, 3. The "\termcap_string ? (not match..." expression
X # handles 1.
X
X if find("\\",\termcap_string)
X then f := open(termcap_string)
X /f := open("termcap") |
X er("getentry","I can't access your termcap file",1)
X
X getline := create read_file(f)
X
X while line := @getline do {
X if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
X entry := ""
X while (\line | @getline) ? {
X if entry ||:= 1(tab(find(":")+1), pos(0))
X then {
X close(f)
X # if entry ends in tc= then add in the named tc entry
X entry ?:= tab(find("tc=")) ||
X # recursively fetch the new termcap entry
X (move(3), getentry(tab(find(":"))) ?
X # remove the name field from the new entry
X (tab(find(":")+1), tab(0)))
X return entry
X }
X else {
X \line := &null # must precede the next line
X entry ||:= trim(trim(tab(0),'\\'),':')
X }
X }
X }
X }
X }
X
X close(f)
X er("getentry","can't find and/or process your termcap entry",3)
X
Xend
X
X
X
Xprocedure read_file(f)
X
X # Suspends all non #-initial lines in the file f.
X # Removes leading tabs and spaces from lines before suspending
X # them.
X
X local line
X
X \f | er("read_tcap_file","no valid termcap file found",3)
X while line := read(f) do {
X match("#",line) & next
X line ?:= (tab(many('\t ')) | &null, tab(0))
X suspend line
X }
X
X fail
X
Xend
X
X
X
Xprocedure maketc_table(entry)
X
X # Maketc_table(s) (where s is a valid termcap entry for some
X # terminal-type): Returns a table in which the keys are termcap
X # capability designators, and the values are the entries in
X # "entry" for those designators.
X
X local k, v
X
X /entry & er("maketc_table","no entry given",8)
X if entry[-1] ~== ":" then entry ||:= ":"
X
X tc_table := table()
X
X entry ? {
X
X tab(find(":")+1) # tab past initial (name) field
X
X while tab((find(":")+1) \ 1) ? {
X
X &subject == "" & next
X if k := 1(move(2), ="=")
X then tc_table[k] := Decode(tab(find(":")))
X else if k := 1(move(2), ="#")
X then tc_table[k] := integer(tab(find(":")))
X else if k := 1(tab(find(":")), pos(-1))
X then tc_table[k] := true()
X else er("maketc_table", "your termcap file has a bad entry",3)
X }
X }
X
X return tc_table
X
Xend
X
X
X
Xprocedure getval(id)
X
X /tc_table := maketc_table(getentry(getname())) |
X er("getval","can't make a table for your terminal",4)
X
X return \tc_table[id] | fail
X # er("getval","the current terminal doesn't support "||id,7)
X
Xend
X
X
X
Xprocedure Decode(s)
X
X # Does things like turn ^ plus a letter into a genuine control
X # character.
X
X new_s := ""
X
X s ? {
X while new_s ||:= tab(upto('\\^')) do {
X chr := move(1)
X if chr == "\\" then {
X new_s ||:= {
X case chr2 := move(1) of {
X "\\" : "\\"
X "^" : "^"
X "E" : "\e"
X "b" : "\b"
X "f" : "\f"
X "n" : "\n"
X "r" : "\r"
X "t" : "\t"
X default : {
X if any(&digits,chr2) then {
X char(integer("8r"||chr2||move(2 to 0 by -1))) |
X er("Decode","bad termcap entry",3)
X }
X else chr2
X }
X }
X }
X }
X else new_s ||:= char(ord(map(move(1),&lcase,&ucase)) - 64)
X }
X new_s ||:= tab(0)
X }
X
X return new_s
X
Xend
X
X
X
Xprocedure igoto(cm,col,line)
X
X local colline, range, increment, str, outstr, chr, x, y
X
X if col > (tc_table["co"]) | line > (tc_table["li"]) then {
X colline := string(\col) || "," || string(\line) | string(\col|line)
SHAR_EOF
true || echo 'restore of itlibdos.icn failed'
fi
echo 'End of part 2'
echo 'File itlibdos.icn is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
From icon-group-request@arizona.edu Tue Jan 1 21:52:55 1991
Resent-From: icon-group-request@arizona.edu
Received: from Arizona.edu (Hopey.Telcom.Arizona.EDU) by megaron.cs.arizona.edu (5.61/15) via SMTP
id AA14640; Tue, 1 Jan 91 21:52:55 -0700
Received: from ucbvax.Berkeley.EDU by Arizona.edu; Tue, 1 Jan 91 21:51 MST
Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA29778; Tue, 1 Jan 91 20:43:37
-0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews for
icon-group@arizona.edu (icon-group@arizona.edu) (contact
usenet@ucbvax.Berkeley.EDU if you have questions)
Resent-Date: Tue, 1 Jan 91 21:52 MST
Date: 2 Jan 91 02:54:28 GMT
From: netnews.upenn.edu!msuinfo!midway!quads.uchicago.edu!goer@rutgers.edu
Subject: UNIX port of bj, part 1 of 3
Sender: icon-group-request@arizona.edu
Resent-To: icon-group@cs.arizona.edu
To: icon-group@arizona.edu
Resent-Message-Id: <DEC49C5CF08940048B@Arizona.edu>
Message-Id: <1991Jan2.025428.21379@midway.uchicago.edu>
Organization: University of Chicago
X-Envelope-To: icon-group@CS.Arizona.EDU
X-Vms-To: icon-group@Arizona.edu
Tenaglia's blackjack game was very cleanly written, and I ported
it before dinner tonight. Some of the character graphics and fonts
couldn't be reproduced portably using standard Unix terminals, so
I had to remove them. Oh well.
Needless to say, I haven't tested this program terribly thoroughly
on any system but my own, and even there some bugs might remain.
Still, I don't expect that anyone will encounter any big problems
running it (or fixing it up).
It's a nice game. In fact, I must hurry up, since my son is breathing
down my neck to let him have the console so that he can run it here at
home. Here's the first of three shell archives.
-Richard (goer@sophist.uchicago.edu)
stty: Operation not supported on socket
---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 01/02/1991 02:37 UTC by goer@sophist.uchicago.edu
# Source directory /u/richard/Bj
#
# existing files will NOT be overwritten unless -c is specified
# This format requires very little intelligence at unshar time.
# "if test", "cat", "rm", "echo", "true", and "sed" may be needed.
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 10389 -r--r--r-- bj.icn
# 12240 -r--r--r-- itlib.icn
# 14586 -r--r--r-- itlibdos.icn
# 2391 -r--r--r-- termcap.dos
# 1654 -rw-r--r-- README
# 754 -rw-r--r-- Makefile.dist
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= bj.icn ==============
if test -f 'bj.icn' -a X"$1" != X"-c"; then
echo 'x - skipping bj.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting bj.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bj.icn' &&
X############################################################################
X#
X# Names: bj.icn
X#
X# Title: blackjack game
X#
X# Author: Chris Tenaglia (modified by Richard L. Goerwitz)
X#
X# Version: 1.1
X#
X############################################################################
X#
X# Simple but fun blackjack game. The original version was for an ANSI
X# screen. This version has been modified to work with the Unix termcap
X# database file.
X#
X############################################################################
X#
X# Links:
X#
X############################################################################
X
Xglobal deck, message, lookup,
X user_money, host_money,
X user_hand, host_hand
X
Xprocedure main(param)
X user_money := integer(param[1]) | 3 ; host_money := user_money
X write(screen("cls"))
X# Most terminals don't do oversize characters like this.
X# write(screen("cls")," ",screen("top"),screen("hinv"),
X# "BLACK JACK",screen("norm"))
X# write(" ",screen("bot"),screen("hinv"),
X# "BLACK JACK",screen("norm"))
X write(screen("high")," ---- BLACK JACK ----",screen("norm"))
X bonus := 0
X repeat
X {
X if not any('y',(map(input(at(1,3) || " " || screen("under") ||
X "Play a game? y/n : "|| screen("norm") ||
X screen("eeol")))[1])) then break
X every writes(at(1,3|4),screen("eeos"))
X display_score()
X deck := shuffle()
X message := ""
X user_hand := [] ; host_hand := []
X put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
X put(user_hand,pop(deck)) ; put(host_hand,pop(deck))
X user_points := first(host_hand[1])
X if user_points > 21 then
X {
X writes(at(1,13),user_points," points. You went over. You lose.")
X user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
X display_score()
X next
X }
X display_host(2)
X host_points := second(user_points)
X if host_points > 21 then
X {
X writes(at(50,22),host_points," points. ",&host ? tab(find(" ")),
X " went over.")
X writes(at(1,13),screen("hiblink"),"You win.",screen("norm"))
X host_money -:= 1 ; user_money +:= 1 + bonus ; bonus := 0
X display_score()
X next
X }
X if host_points = user_points then
X {
X writes(at(1,22),screen("hiblink"),"It's a draw at ",user_points,
X ". The ANTY goes to bonus.",screen("norm"))
X bonus +:= 2 ; host_money -:= 1 ; user_money -:= 1
X display_score()
X next
X }
X writes(at(20,12),user_points," points for user.")
X writes(at(1,14),host_points," points for ",&host ? tab(find(" ")))
X if user_points < host_points then
X {
X write(at(1,22),screen("hiblink"),&host ? tab(find(" "))," wins.",
X screen("norm"),screen("eeol"))
X user_money -:= 1 ; host_money +:= 1 + bonus ; bonus := 0
X display_score()
X next
X } else {
X writes(at(1,12),screen("hiblink"),"You win.",screen("norm"),
X screen("eeol"))
X user_money +:= 1 + bonus ; host_money -:= 1 ; bonus := 0
X display_score()
X next
X }
X }
X write(screen("clear"))
X end
X
X#
X# THIS PROCEDURE ALLOWS THE USER TO PLAY AND TAKE HITS
X#
Xprocedure first(host_card)
X display_user()
X display_host(1)
X points := value(user_hand) # just in case
X writes(at(1,9),"(",points,") ")
X repeat
X if any('hy',map(input(at(1,23) || "Hit ? y/n : " || screen("eeol")))) then
X {
X put(user_hand,pop(deck))
X display_user()
X if (points := value(user_hand)) > 21 then return points
X writes(at(1,9),"(",points,") ")
X } else break
X (points > 0) | (points := value(user_hand))
X writes(at(1,9),"(",points,") ")
X write(at(60,11),"You stay with ",points)
X return points
X end
X
X#
X# THIS SECOND PROCEDURE IS THE HOST PLAYING AGAINST THE USER
X#
Xprocedure second(ceiling)
X static limits
X initial limits := [14,14,15,15,19,16,17,18]
X stop_at := ?limits ; points := 0
X until (points := value(host_hand)) > stop_at do
X {
X if points > ceiling then return points
X writes(at(1,19),"(",points,") ")
X# write(at(1,22),screen("eeol"),&host," will take a hit.",screen("eeol"))
X write(at(1,22),screen("eeol"),&host ? tab(find(" ")),
X " will take a hit.",screen("eeol"))
X put(host_hand,pop(deck))
X display_host(2)
X }
X (points > 0) | (points := value(host_hand))
X writes(at(1,19),"(",points,") ")
X return points
X end
X
X#
X# THIS ROUTINE DISPLAYS THE CURRENT SCORE
X#
Xprocedure display_score()
X writes(screen("nocursor"))
X writes(screen("dim"),at(1,7),"Credits",screen("norm"))
X writes(screen("high"),at(1,8),right(user_money,7),screen("norm"))
X writes(screen("dim"),at(1,17),"Credits",screen("norm"))
X writes(screen("high"),at(1,18),right(host_money,7),screen("norm"))
X end
X#
X# THIS PROCEDURE EVALUATES THE POINTS OF A HAND. IT TRIES TO MAKE THEM
X# AS HIGH AS POSSIBLE WITHOUT GOING OVER 21.
X#
Xprocedure value(sample)
X hand := copy(sample)
X possible := []
X repeat
X {
X sum := 0
X every card := !hand do sum +:= lookup[card[1]]
X put(possible,sum)
X if Aces(hand) == "none" then break else
X every i := 1 to *hand do if hand[i][1] == "A" then hand[i][1] := "a"
X }
X every score := !possible do
X if score <= 21 then return score
X return possible[1]
X end
X
X#
X# ARE THERE ANY 11 POINT ACES LEFT IN HAND
X#
Xprocedure Aces(cards)
X every look := !cards do if look[1] == "A" then return "some"
X return "none"
X end
X
X#
X# THIS ROUTINE DISPLAYS THE USER HAND AND STATUS
X#
Xprocedure display_user()
X writes(screen("nocursor"),at(1,6),screen("hinv"),"USER",screen("norm"))
X x := 10 ; y := 4
X every card := !user_hand do
X {
X display(card,x,y)
X x +:= 7
X }
X end
X
X#
X# THIS ROUTINE DISPLAYS THE HOST HAND AND STATUS
X#
Xprocedure display_host(flag)
X writes(screen("nocursor"),at(1,16),screen("hinv"),
X &host ? tab(find(" ")),screen("norm"))
X x := 10 ; y := 14 ; /flag := 0
X every card := !host_hand do
X {
X if (flag=1) & (x=10) then card := "XX"
X display(card,x,y)
X x +:= 7
X }
X end
X
X#
X# THIS ROUTINE DISPLAYS A GIVEN CARD AT A GIVEN X,Y SCREEN LOCATION
X#
Xprocedure display(card,x,y)
X all := [] ; j := y
X if find(card[2],"CS") then card := screen("hinv") || card || screen("norm")
X# shape := [at(x,(j+:=1)) || screen("gchar") || "lqqqqqqqk"]
X shape := [at(x,(j+:=1)) || screen("inv") || " " || screen("norm")]
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
X " " || card || " " || screen("inv") || " " || screen("norm"))
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
X " " || screen("inv") || " " || screen("norm"))
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
X " " || screen("inv") || " " || screen("norm"))
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
X " " || screen("inv") || " " || screen("norm"))
X# put(shape,at(x,(j+:=1)) || "x x")
X# put(shape,at(x,(j+:=1)) || "x x")
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm") ||
X " " || card || " " || screen("inv") || " " || screen("norm"))
X# put(shape,at(x,(j+:=1)) || "mqqqqqqqj" || screen("nchar"))
X put(shape,at(x,(j+:=1)) || screen("inv") || " " || screen("norm"))
X put(all,shape)
X x +:= 14
X while shape := pop(all) do every writes(!shape)
X end
X
X#
X# THIS ROUTINE SHUFFLES THE CARD DECK
X#
Xprocedure shuffle()
X static faces, suits
X local cards, i
X initial {
X &random := map(&clock,":","7") # initial on multiple shuffles
X faces := ["2","3","4","5","6","7","8","9","T","J","Q","K","A"]
X suits := ["D","H","C","S"]
X lookup := table(0)
X every i := 2 to 9 do insert(lookup,string(i),i)
X insert(lookup,"T",10)
X insert(lookup,"J",10)
X insert(lookup,"Q",10)
X insert(lookup,"K",10)
X insert(lookup,"A",11)
X insert(lookup,"a",1)
X }
X cards := []
X every put(cards,!faces || !suits)
X every i := *cards to 2 by -1 do cards[?i] :=: cards[i]
X return cards
X end
X
X#
X# THIS ROUTINE PARSES A STRING WITH RESPECT TO SOME DELIMITER
X#
Xprocedure parse(line,delims)
X static chars
X chars := &cset -- delims
X tokens := []
X line ? while tab(upto(chars)) do put(tokens,tab(many(chars)))
X return tokens
X end
X
X#
X# THIS ROUTINE PROMPTS FOR INPUT AND RETURNS A STRING
X#
Xprocedure input(prompt)
X writes(screen("cursor"),prompt)
X return read()
X end
X
X
X#
X# THIS ROUTINE SETS THE VIDEO OUTPUT ATTRIBUTES FOR VT102 OR LATER
X# COMPATIBLE TERMINALS.
X#
Xprocedure screen(attr)
X initial if getval("ug"|"mg"|"sg") > 0 then
X er("screen","oops, magic cookie terminal!",34)
X return {
X case attr of
X {
X "cls" : getval("cl")
X "clear": getval("cl")
X # HIGH INTENSITY & INVERSE
X "hinv" : (getval("md") | "") || getval("so")
X "norm" : (getval("se") | "") || (getval("me") | "") || (getval("ue")|"")
X # LOW INTENSITY VIDEO
X "dim" : getval("mh"|"me")
X "blink": getval("mb"|"md"|"so")
X # HIGH INTENSITY BLINKING
X "hiblink": (getval("md") | "") || getval("mb") | getval("so")
X "under": getval("us"|"md"|"so")
X "high" : getval("md"|"so"|"ul")
X "inv" : getval("so"|"md"|"ul")
X # ERASE TO END OF LINE
X "eeol" : getval("ce")
X # ERASE TO START OF LINE
X "esol" : getval("cb")
X # ERASE TO END OF SCREEN
X "eeos" : getval("cd")
X # MAKE CURSOR INVISIBLE
X "cursor": getval("vi"|"CO") | ""
X # MAKE CURSOR VISIBLE
X "nocursor": getval("ve"|"CF") | ""
X# # START ALTERNATE FONT <- very non-portable
X# "gchar": getval("as") | ""
X# # END ALTERNATE FONT
X# "nchar": getval("ae") | ""
X# "light": return "\e[?5h" # LIGHT COLORED SCREEN
X# "dark" : return "\e[?5l" # DARK COLORED SCREEN
X# "80" : return "\e[?3l" # 80 COLUMNS ON SCREEN
X# "132" : return "\e[?3h" # 132 COLUMNS ON SCREEN
X# "smooth": return "\e[?4h" # SMOOTH SCREEN SCROLLING
X# "jump" : return "\e[?4l" # JUMP SCREEN SCROLLING
X default : er("screen",attr||" is just too weird for most terminals",34)
X } | er("screen","I just can't cope with your terminal.",35)
X }
X end
X
X#
X# THIS ROUTINE SETS THE CURSOR TO A GIVEN X (COL) Y(ROW) SCREEN LOCATION
X#
Xprocedure at(x,y)
X# return "\e[" || y || ";" || x || "f"
X return igoto(getval("cm"),x,y)
X end
X
SHAR_EOF
true || echo 'restore of bj.icn failed'
rm -f _shar_wnt_.tmp
fi
# ============= itlib.icn ==============
if test -f 'itlib.icn' -a X"$1" != X"-c"; then
echo 'x - skipping itlib.icn (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting itlib.icn (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'itlib.icn' &&
X########################################################################
X#
X# Name: itlib.icn
X#
X# Title: Icon termlib-type tools
X#
X# Author: Richard L. Goerwitz
X#
X# Version: 1.23
X#
X#########################################################################
X#
X# I place this and future versions of itlib in the public domain - RLG
X#
X#########################################################################
X#
X# The following library represents a series of rough functional
X# equivalents to the standard Unix low-level termcap routines. They
X# are not meant as exact termlib clones. Nor are they enhanced to
X# take care of magic cookie terminals, terminals that use \D in their
X# termcap entries, or, in short, anything I felt would not affect my
X# normal, day-to-day work with ANSI and vt100 terminals.
X#
X# Requires: A unix platform & co-expressions. There is an MS-DOS
X# version, itlibdos.icn.
X#
X# setname(term)
X# Use only if you wish to initialize itermlib for a terminal
X# other than what your current environment specifies. "Term" is the
X# name of the termcap entry to use. Normally this initialization is
X# done automatically, and need not concern the user.
X#
X# getval(id)
X# Works something like tgetnum, tgetflag, and tgetstr. In the
X# spirit of Icon, all three have been collapsed into one routine.
X# Integer valued caps are returned as integers, strings as strings,
X# and flags as records (if a flag is set, then type(flag) will return
X# "true"). Absence of a given capability is signalled by procedure
X# failure.
X#
X# igoto(cm,destcol,destline) - NB: default 1 offset (*not* zero)!
X# Analogous to tgoto. "Cm" is the cursor movement command for
X# the current terminal, as obtained via getval("cm"). Igoto()
X# returns a string which, when output via iputs, will cause the
X# cursor to move to column "destcol" and line "destline." Column and
X# line are always calculated using a *one* offset. This is far more
X# Iconish than the normal zero offset used by tgoto. If you want to
X# go to the first square on your screen, then include in your program
X# "iputs(igoto(getval("cm"),1,1))."
X#
X# iputs(cp,affcnt)
X# Equivalent to tputs. "Cp" is a string obtained via getval(),
X# or, in the case of "cm," via igoto(getval("cm"),x,y). Affcnt is a
X# count of affected lines. It is only relevant for terminals which
X# specify proportional (starred) delays in their termcap entries.
X#
X# Bugs: I have not tested these routines on terminals that require
X# padding. These routines WILL NOT WORK if your machines stty com-
X# mand has no -g option (tisk, tisk). This includes NeXT worksta-
X# tions, and some others that I haven't had time to pinpoint.
X#
X##########################################################################
X#
X# Requires: UNIX, co-expressions
X#
X# See also: iscreen.icn (a set of companion utilities)
X#
X##########################################################################
X
X
Xglobal tc_table, tty_speed
Xrecord true()
X
X
Xprocedure check_features()
X
X local in_params, line
X # global tty_speed
X
X initial {
X find("unix",map(&features)) |
X er("check_features","unix system required",1)
X find("o-expres",&features) |
X er("check_features","co-expressions not implemented - &$#!",1)
X system("/bin/stty tabs") |
X er("check_features","can't set tabs option",1)
X }
X
X # clumsy, clumsy, clumsy, and probably won't work on all systems
X tty_speed := getspeed()
X return "term characteristics reset; features check out"
X
Xend
X
X
X
Xprocedure setname(name)
X
X # Sets current terminal type to "name" and builds a new termcap
X # capability database (residing in tc_table). Fails if unable to
X # find a termcap entry for terminal type "name." If you want it
X # to terminate with an error message under these circumstances,
X # comment out "| fail" below, and uncomment the er() line.
X
X #tc_table is global
X
X check_features()
X
X tc_table := table()
X tc_table := maketc_table(getentry(name)) | fail
X # er("setname","no termcap entry found for "||name,3)
X return "successfully reset for terminal " || name
X
Xend
X
X
X
Xprocedure getname()
X
X # Getname() first checks to be sure we're running under Unix, and,
X # if so, tries to figure out what the current terminal type is,
X # checking successively the value of the environment variable
X # TERM, and then the output of "tset -". Terminates with an error
X # message if the terminal type cannot be ascertained.
X
X local term, tset_output
X
X check_features()
X
X if not (term := getenv("TERM")) then {
X tset_output := open("/bin/tset -","pr") |
X er("getname","can't find tset command",1)
X term := !tset_output
X close(tset_output)
X }
X return \term |
X er("getname","can't seem to determine your terminal type",1)
X
Xend
X
X
X
Xprocedure er(func,msg,errnum)
X
X # short error processing utility
X write(&errout,func,": ",msg)
X exit(errnum)
X
Xend
X
X
X
Xprocedure getentry(name, termcap_string)
X
X # "Name" designates the current terminal type. Getentry() scans
X # the current environment for the variable TERMCAP. If the
X # TERMCAP string represents a termcap entry for a terminal of type
X # "name," then getentry() returns the TERMCAP string. Otherwise,
X # getentry() will check to see if TERMCAP is a file name. If so,
X # getentry() will scan that file for an entry corresponding to
X # "name." If the TERMCAP string does not designate a filename,
X # getentry() will scan /etc/termcap for the correct entry.
X # Whatever the input file, if an entry for terminal "name" is
X # found, getentry() returns that entry. Otherwise, getentry()
X # fails.
X
X local f, getline, line, nm, ent1, ent2
X
X # You can force getentry() to use a specific termcap file by cal-
X # ling it with a second argument - the name of the termcap file
X # to use instead of the regular one, or the one specified in the
X # termcap environment variable.
X /termcap_string := getenv("TERMCAP")
X
X if \termcap_string ? (not match("/"), pos(0) | tab(find("|")+1), =name)
X then return termcap_string
X else {
X
X # The logic here probably isn't clear. The idea is to try to use
X # the termcap environment variable successively as 1) a termcap en-
X # try and then 2) as a termcap file. If neither works, 3) go to
X # the /etc/termcap file. The else clause here does 2 and, if ne-
X # cessary, 3. The "\termcap_string ? (not match..." expression
X # handles 1.
X
X if find("/",\termcap_string)
X then f := open(termcap_string)
X /f := open("/etc/termcap") |
X er("getentry","I can't access your /etc/termcap file",1)
X
X getline := create read_file(f)
X
X while line := @getline do {
X if line ? (pos(1) | tab(find("|")+1), =name, any(':|')) then {
X entry := ""
X while (\line | @getline) ? {
X if entry ||:= 1(tab(find(":")+1), pos(0))
X then {
X close(f)
X # if entry ends in tc= then add in the named tc entry
X entry ?:= tab(find("tc=")) ||
X # recursively fetch the new termcap entry
X (move(3), getentry(tab(find(":"))) ?
X # remove the name field from the new entry
SHAR_EOF
true || echo 'restore of itlib.icn failed'
fi
echo 'End of part 1'
echo 'File itlib.icn is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0