|Tads| How do you do a computer?

3 views
Skip to first unread message

Ens Regis

unread,
Oct 28, 1998, 3:00:00 AM10/28/98
to

Really. I would like to know how to do a "database" of sorts in Tads. I want it
to accept the name of someone, the password, a keycard in a separate slot, and
after all this, be able to have a menu of 5 or so options, possibly
sub-branching off of this. And I have NO idea how to do it.

Please help me out.

(BTW, if I actually COMPLETE the game, I will give credit where it is due.)

-Ensign Regis
-Ensign Regis
A cow with no legs is ground beef.

Dan Shiovitz

unread,
Oct 28, 1998, 3:00:00 AM10/28/98
to
In article <19981027213252...@ngol03.aol.com>,

Ens Regis <ensr...@aol.com> wrote:
>
>Really. I would like to know how to do a "database" of sorts in
>Tads. I want it
>to accept the name of someone, the password, a keycard in a separate slot, and
>after all this, be able to have a menu of 5 or so options, possibly
>sub-branching off of this. And I have NO idea how to do it.
[..]

You can read in a line of text from the keyboard with the input()
function. I've got a simple menu module I've been meaning to stick on
gmd. I guess I'll do that. It's got an example of the input() function
too. You'll have to be more specific about the other stuff you want.

>-Ensign Regis
--
Dan Shiovitz || d...@cs.wisc.edu || http://www.cs.wisc.edu/~dbs
"...Incensed by some crack he had made about modern enlightened
thought, modern enlightened thought being practically a personal buddy
of hers, Florence gave him the swift heave-ho and--much against my
will, but she seemed to wish it--became betrothed to me." - PGW, J.a.t.F.S.

Dan Shiovitz

unread,
Oct 28, 1998, 3:00:00 AM10/28/98
to
In article <19981027213252...@ngol03.aol.com>,
Ens Regis <ensr...@aol.com> wrote:
>
>Really. I would like to know how to do a "database" of sorts in
>Tads. I want it
>to accept the name of someone, the password, a keycard in a separate slot, and
>after all this, be able to have a menu of 5 or so options, possibly
>sub-branching off of this. And I have NO idea how to do it.
[..]

You can read in a line of text from the keyboard with the input()
function. I've got a simple menu module I've been meaning to stick on
gmd. I guess I'll do that. It's got an example of the input() function
too. You'll have to be more specific about the other stuff you

want. Are there supposed to be several names/passwords or just one? Is
there some sort of matching that has to go on between all these things
and the card, or what?

Dan Shiovitz

unread,
Oct 28, 1998, 3:00:00 AM10/28/98
to
In article <19981027213252...@ngol03.aol.com>,
Ens Regis <ensr...@aol.com> wrote:
>
>Really. I would like to know how to do a "database" of sorts in
>Tads. I want it
>to accept the name of someone, the password, a keycard in a separate slot, and
>after all this, be able to have a menu of 5 or so options, possibly
>sub-branching off of this. And I have NO idea how to do it.
[..]

You can read in a line of text from the keyboard with the input()
function. I've got a simple menu module I've been meaning to stick on
gmd. I guess I'll do that. It's got an example of the input() function
too. You'll have to be more specific about the other stuff you want.

>-Ensign Regis

Ens Regis

unread,
Oct 28, 1998, 3:00:00 AM10/28/98
to

In article <716f96$o...@spool.cs.wisc.edu>, d...@cs.wisc.edu (Dan Shiovitz)
writes:

>You can read in a line of text from the keyboard with the input()
>function. I've got a simple menu module I've been meaning to stick on
>gmd. I guess I'll do that. It's got an example of the input() function
>too. You'll have to be more specific about the other stuff you

>want. Are there supposed to be several names/passwords or just one? Is
>there some sort of matching that has to go on between all these things
>and the card, or what?

OK, I'll be more specific. I need to be able to:
Type in about 14 or so names, 14 passwords (one for each), and have an "access
card" to insert into a slot when a specific name and password is typed in.
After this, a simple menu interface should pop up, with 4 options + an "exit"
command.

Rene van 't Veen

unread,
Oct 29, 1998, 3:00:00 AM10/29/98
to

Ens Regis wrote in message <19981028160231...@ngol07.aol.com>...


This computer: with a lot of hard work.

No kidding.

For instance:

You need to define objects for a keyboard and a screen
(the screen is probably just "intelligent" decoration).
Oh, and a slot. And while you are at it, put a post-it
note giving instructions to users somewhere in that room
too.

The keyboard servers as your actual computer and is
implemented as a state machine, with states like:
1 - waiting
2 - name entered, but not found
3 - name entered, waiting for password
4 - received password, password ok, waiting access card
5 - received password, password not ok, computer blocked
6 - all names and passwords entered and ok, display menu
7 ....

You need to define/modify a verb, such that it
will accept "TYPE 'JOHN SMITH' ON KEYBOARD.

In the keyboard implement the verIoTypeOn en ioTypeOn
routines to go with the verb.

A property of the keyboard is a list of names that
the computer will accept, in you ioTypeOn routine
verify that this is a name you need. If it is a name
you want you advance the state of the keyboard from
0 (waiting) to 3. In doing so, give the player
feedback and send that message to the screen to (so
the screen's readdesc or ldesc is different depending
on the state of the keyboard/computer).

Read passwords (possibly using the input() routine)
until you are ready to accept/test it. When it is
accepted the state of the computer is advanced from
3 to 4. If it is 5 you want to block the player's access
to the computer before you reset the state to 5 again,
at least for a few turns - a fuse would be ideal, etc.

And the list goes on ...

----
"Would you tell me, please, which way I ought to go from here?"
"That depends a good deal on where you want to get to," said the Cat
---
Rene van 't Veen - remove the 'nospam's' from the reply-to to email me.


TenthStone

unread,
Oct 31, 1998, 3:00:00 AM10/31/98
to
ensr...@aol.com (Ens Regis) caused this to appear in our collective minds
on 28 Oct 1998 21:02:31 GMT:

>
>In article <716f96$o...@spool.cs.wisc.edu>, d...@cs.wisc.edu (Dan Shiovitz)
>writes:
>
>>You can read in a line of text from the keyboard with the input()
>>function. I've got a simple menu module I've been meaning to stick on
>>gmd. I guess I'll do that. It's got an example of the input() function
>>too. You'll have to be more specific about the other stuff you
>>want. Are there supposed to be several names/passwords or just one? Is
>>there some sort of matching that has to go on between all these things
>>and the card, or what?
>
>OK, I'll be more specific. I need to be able to:
>Type in about 14 or so names, 14 passwords (one for each), and have an "access
>card" to insert into a slot when a specific name and password is typed in.
>After this, a simple menu interface should pop up, with 4 options + an "exit"
>command.

Hmm.

The obvious question is whether these name/password combinations need to
be constant in the game. I'll try to provide a flexible design.

// Begin code.
// Let's get what we're doing straight. We're going to have a specific
// class for users; each user will be a seperate object. This shouldn't
// pose a problem. Just a blank class, for use with firstobj; we
// provide defaults.

class computeruser: object
userid = 'guest'
userpasswd = ''
usercard = nil // can be a list
;

// And an access-card class: blank, with defaults.
class accesscard: item
noun = 'card' 'plastic' 'piece'
adjective = 'access' 'network' 'plastic' 'thin' 'durable'
plural = 'cards'
sdesc = "<< self.name >>'s access card"
name = "guest"
ldesc = "The thin card is made of a durable plastic; a bar code
and a magnetic strip on the reverse doubtless contain the
same information as can be clearly read from the obverse:
\n\t\tNetwork Access Card
\n\tFor the use of: << self.name >>"
;

// Now, the more gritty details. We want a function which checks whether
// the given user information is valid. To be general, we pass a
// "network" object, which checkaccess consults for the network's user
// class (here, computeruser) and the information for the current
// login-attempt.

// checkaccess will return one of four values:
// 0 - invalid user
// 1 - invalid password
// 2 - invalid card
// object - success (returns user object)
checkaccess: function( net ) {
local o, c := net.userclass, attemped, actual, high := 0;
for (o := firstobj( c ); o; o := nextobj( c, o )) {
if (o.usercard = net.usercard) {
if (not net.userid_cs) {
attempted := lower( net.userid );
actual := lower( o.userid );
}
else {
attempted := net.userid;
actual := o.userid;
}
if (atttempted = actual) {
if (not net.userpasswd_cs) {
attempted := lower( net.userpasswd );
actual := lower( o.userpasswd );
}
else {
attempted := net.userpasswd;
actual := o.userpasswd;
}
if (attempted = actual) {
attempted := net.part_cardslot.contents[1];
actual := o.usercard;
if (actual = nil) return o;
// don't even check if user card is nil.
actual := [] + actual; // make it a list; if it is a
// list, this shouldn't change anything.
if (intersect( attemped, actual )) return o;
}
else if (high = 1) high = 2;
}
else if (high = 0) high := 1;
}
}
return high;
}

// The network object needn't be an independent object; it just
// shouldn't be a user information object itself. Here, we're defining
// the terminal class to be any computer which can logged into.
// I've flouted convention a bit here by creating a single object for
// almost all of the computer. As proposed by Rene, it's essentially
// a state machine; my model is a bit simpler in some ways, and
// much more complex in others. As with real networks, this
// terminal collects all of the information before ever verifying the
// data, which reduces the number of possible states. I've also
// allowed for as many generalities as possible in the game: one
// could easily have twenty terminals in a room (although one would
// need a slot and a button object for each) and as many networks as one
// feels like in the game. Users can be duplicated from one network to
// the next (simply give the object two classes).

// In order for a terminal to function, it needs two auxiliary objects:
// a cardslot and readybutton (note that these happen to be the class
// identifiers). The terminal should be defined with its part_cardslot
// and part_readybutton properties set to the appropriate objects; these
// should, in turn, have their part_terminal properties set to point to
// their terminal. terminal.part_cardslot and readybutton.part_terminal
// are the only imperative ones as of this writing; however, it would be
// wise to set the others in case you need to determine them for some
// reason.
class terminal: fixeditem, readable
noun = 'terminal' 'computer' 'monitor' 'keyboard' 'cpu'
adjective = 'network' 'one-piece'
userid = ''
userpasswd = ''
usercard = nil
userid_cs = nil // Should the user id check be case-sensitive?
userpasswd_cs = nil // Same question with password.
userclass = nil
sdesc = "network terminal"
ldesc = "Like most on-campus network terminals, this is a
one-piece computer, meaning the monitor and CPU
are built together in a single unit. It has no floppy
drive, but instead there is a slot for access cards, with
a multi-use button. A keyboard sits to one side.
\nThe screen currently reads:\b<< self.readdesc >>"
verDoUnplug( actor ) = "Meddling about with the connections of the
terminals would only bother the other users and incur the
wrath of the netmaster."
curprogram = login
curstate = 1
curuser = nil
readdesc = {
self.curprogram.output( self );
}
verIoTypeOn( actor ) = {}
ioTypeOn( actor, dobj ) = {
if (dobj <> strObj and dobj <> numObj) "I'm not sure what
you intend to type on << self.thedsec >>. ";
else {
local v;
if (dobj = numObj) v := cvtstr( dobj.value );
else v := dobj.value;
self.curprogram.getinput( self, v);
}
}
part_cardslot = nil
part_readybutton = nil
refresh = {
self.Refresh;
self.curpogram.output( self );
}
Refresh = "\^<< self.thedesc >> blinks and displays:\n\t"
login_msg = "NETWORK LOGIN" // Displayed on login screen
login_getid = "USERID: " // Username prompt
login_getpasswd = "PASSWD: " // Password prompt
login_getcard = "INSERT CARD AND PUSH READY"
Login = "LOGIN SUCCESSFUL"
login_success( u ) = {
self.curuser := u;
self.Login;
self.curprogram := self.login_program;
self.curprogram.output( self );
} // handles successful login. The only other processing
// done upon success is to clear the two login variables
// (terminal.userid and terminal.userpasswd) and set
// terminal.curstate to 1; therefore, any change in
// program must occur here.
login_program = login; // Just login again, since we don't have
// anything better to do.
login_failure( p ) = "INVALID LOGIN"
// handles login; p is a numerical value as given by
// checkaccess:
// 1: invalid user
// 2: invalid password
// 3: invalid access card
;

// This class exists just to differentiate a certain type of network from
// another; if you have only have one network, just merge these lines
// into the terminal class.

// The three
class uninet: terminal
adjective = 'uninet'
thedesc = "UniNet terminal << self.value >>"
ldesc = "Like most on-campus network terminals, this is a
one-piece computer, meaning the monitor and CPU
are built together in a single unit. It has no floppy
drive, but instead there is a slot for access cards, with
a multi-use button. A keyboard sits to one side. This
terminal is numbered << self.value >>.
\nThe screen currently reads:\b<< self.readdesc >>"
value = 1
userclass = computeruser
userid_cs = nil
userpasswd_cs = true
login_msg = "UniNet Login (#<< self.value >>)"
login_getid = "User name: "
login_getpasswd = "User password: "
login_getcard = "Please insert your identification card if
necessary and push Ready.";
Login = "<< self.Refresh >>
Successfully logged in as user << term.curuser.userid >>
on terminal << self.value >>. "
login_program = usermenu
login_failure( p ) = {
self.Refresh;
switch (p) {
case 1: "Invalid user name."; break;
case 2: "Invalid password."; break;
case 3: "Invalid access card."; break;
}
}
;

class cardslot: fixeditem, container
noun = 'slot'
adjective = 'card' 'access'
sdesc = "access card slot"
ldesc = {
if (self.contents) "There is an access card in the slot.";
else "The access card slot is presently empty. ";
}
verIoPutIn( actor ) = {}
ioPutIn( actor, dobj ) = {
if (self.contents) "The slot is occupied already. ";
else if (not isclass( dobj, accesscard )) "That cannot fit
in the slot. ";
else pass ioPutIn;
}
part_terminal = nil
;

class readybutton: fixeditem
noun = 'button'
adjective = 'multi-use' 'multiple' 'use' 'ready' 'small' 'grey'
sdesc = "ready button"
ldesc = "The button is small and grey. ";
part_terminal = nil
verDoPress( actor ) = {}
verDoPush( actor ) = {}
doPress( actor ) = { self.doPush( actor ); }
doPush( actor ) = {
if (self.part_terminal) {
self.part_terminal.curprogram.ready(
self.part_terminal );
}
else "This terminal is inoperable; you need to consult
with a network operator before continuing. ";
}
;

// Now we must define our programs, which are basic objects with
// three properties: getinput, output, and ready.

class program: object
output( term ) = {
"[nothing]";
}
;

// program LOGIN
// State Table:
// 1. Waiting for userid
// 2. Waiting for userpasswd
// 3. Waiting for Ready.
login: program
getinput( term, val ) = {
switch ( term.curstate ) {
case 1:
term.userid := val;
term.curstate++;
term.refresh;
break;
case 2:
term.userpasswd := val;
term.curstate++;
term.refresh;
break;
case 3: break;
}
}
output( term ) = {
local s := term.curstate;
"<< term.login_msg >>
\n\t<< term.login_getid >>";
if (s > 1) {
say( term.userid );
"\n\t<< term.login_getpasswd >>";
if (s > 2) {
local i := 1, len := length( term.userpasswd );
for (; i <= len; ++i) "*";
"\n\t<< term.login_getcard >>";
}
}
}
ready( term ) = {
local c := checkaccess( term );
term.curstate := 1;
if (datatype( c ) = 2) term.login_success( c ); // if is object
else term.login_failure( c );
term.userid := '';
term.userpasswd := '';
}
;

// A simple user menu, giving only one option.
usermenu: program
getinput( term, val ) = {
switch (val) {
case '1': case 'logout': case 'quit':
term.curuser := nil;
term.Refresh;
"Logged out from network. ";
break;
default:
term.Refresh;
"Invalid menu option.";
}
}
output( term ) = {
switch( term.curstate ) {
case 1:
"System Menu -- User << term.curuser.userid >>
\n\t1 -- Logout
}
}
ready( term ) = "Pressing the Ready button gets no reaction. ";
;

// Sample:
// First, we'll define a user.
tenthstone: computeruser
userid = 'tenthstone'
userpasswd = 'perturb'
usercard = ts_accesscard
;

// And an access card
ts_accesscard: accesscard
adjective = 'tenthstone' 'tenthstone\'s'
name = "TenthStone"
;

// And a terminal
uninet2001: uninet
location = tabletop
part_cardslot = cardslot2001
part_readybutton = readybutton2001
value = 2001
;

// cardslot
cardslot2001: cardslot
location = tabletop
part_terminal = terminal2001
;

readybutton2001: readybutton
location = tabletop
part_terminal = terminal2001
;

And that should be enough. Good luck; TenthStone out.

-----------

The imperturbable TenthStone
tenth...@hotmail.com mcc...@erols.com mcc...@gsgis.k12.va.us

Reply all
Reply to author
Forward
0 new messages