william tell

This commit is contained in:
whiteline 2025-02-14 14:35:50 +01:00
parent 096fd91378
commit 447b9622a2
4 changed files with 355 additions and 69 deletions

View File

@ -1,4 +1,4 @@
#!/bin/zsh
#xrdb -merge ~/.Xresources.green
urxvt -fn xft:inconsolata-26:antialias=true:hinting=true -letsp 1 -b 26 &
urxvt -fn xft:hack-16 -b 16 &
#xrdb -merge ~/.Xresources

BIN
parking

Binary file not shown.

View File

@ -7,6 +7,56 @@ from time import sleep
from grid import Grid, bresenhams
from fov import fieldOfView
# global variables
game = Universe()
class Tiles():
def __init__(self):
self.floor = Tile('.', "floor", "an unremarkable piece of floor")
self.wall = Tile('#', "wall", "an unremarkable wall", solid=True, transparent=False)
self.door_closed = Tile('+', "closed door", "an unremarkable door", solid=True, transparent=False)
self.door_open = Tile(',', "open door", "an unremarkable door", solid=False, transparent=True)
class Worlds():
def __init__(self):
self.galapagos = World("Galapagos", 80, 23, game.tiles.floor)
self.galapagos.set(12, 12, wall)
self.galapagos.set(13, 12, wall)
self.galapagos.set(14, 12, wall)
self.galapagos.set(15, 12, wall)
self.galapagos.set(16, 12, wall)
self.galapagos.set(16, 13, wall)
self.galapagos.set(16, 14, wall)
self.galapagos.set(18, 12, wall)
self.galapagos.set(18, 13, wall)
self.galapagos.set(18, 14, wall)
self.galapagos.set(12, 13, door_closed)
class Universe():
def __init__(self):
self.run = True
self.window = c.initscr()
c.curs_set(0)
c.raw()
c.echo(False)
self.tiles = Tiles()
self.worlds = Worlds()
self.player = Player("you")
self.behaviors = [self.player]
pb = Body("yourself", '@', "an unremarkable person", c.COLOR_WHITE)
pb.x = 3
pb.y = 6
pb.world = self.worlds.galapagos
self.player.incarnate(pb)
self.galapagos.bodies = [pb]
def run():
while self.run:
for behavior in self.behaviors:
behavior.behave()
c.endwin()
class Tile():
def __init__(self, glyph, name, description, solid=False, transparent=True, color=c.COLOR_WHITE):
self.appearance = glyph
@ -23,15 +73,12 @@ class Tile():
return self.description
class World(Grid):
def __init__(self, window, width, height, initial_tile):
def __init__(self, width, height, initial_tile):
super().__init__(width, height, initial_tile)
self.run = True
self.window = window
self.width = width
self.height = height
self.bodies = []
self.behavior = []
class Behaviour():
def __init__(self, name):
@ -130,7 +177,7 @@ class Player(Behaviour):
else:
self.message("You see nothing here to close.")
case 'q':
self.world.run = False
game.world.run = False
case 'r':
if self.realtime:
self.realtime = False
@ -156,15 +203,15 @@ class Drunkard(Behaviour):
self.body.move((dx, dy))
class Body():
def __init__(self, name, appearence, description, color):
def __init__(self, name, appearence, description, color, world, x, y):
self.name = name
self.appearence = appearence
self.description = description
self.color = color
self.behavior = None
self.world = None
self.x = None
self.y = None
self.world = world
self.x = x
self.y = y
def move(self, direction):
x, y = direction
@ -212,19 +259,39 @@ class Body():
self.world.window.addch(self.y, self.x, self.appearence)
class Conversation(list):
def __init__(self, title, description):
def __init__(self, window, title, description):
self.title = title
self.description = description
def run(self):
# rendering code goes here
pass
valid_responses = filter(lambda r: r.prerequisite() if r.prerequisite else True, self)
selected_response = 0
while True:
window.erase()
window.addstr(0, 0, self.title)
window.addstr(2, 0, self.description)
for i, response in enumerate(valid_responses):
if i == selected_response:
window.addstr(4 + i, 3, ">" + response.name)
else:
window.addstr(4 + i, 4, response.name)
key = window.getkey()
match key:
case 'w':
if selected_response > 0:
selected_response -= 1
case 's':
if selected_response < len(valid_responses):
selected_response += 1
case 'e':
valid_responses[selected_response].respond()
class Response():
def __init__(self, name, text, target=None, prerequisite=None, function=None):
self.name = name
self.text = text
self.target = target
self.prerequisite = prerequisite
self.function = function
def respond(self, title, description):
@ -234,59 +301,4 @@ class Response():
if target:
target.run()
bum_conversation = Conversation("Conversing With a Drunkard", "A foul-smelling drunkard waves to and fro, trying to form words. His tattered clothes are brown with filth.")
bum_conversation.append(Response("Hello? Is everything all right?", "Hargl... hurgl...", target=bum_conversation))
bum_conversation.append(Response("I will take my leave, good sir.", "..."))
p = Player("you")
pb = Body("yourself", '@', "an unremarkable person", c.COLOR_WHITE)
p.incarnate(pb)
floor = Tile('.', "floor", "an unremarkable piece of floor")
wall = Tile('#', "wall", "an unremarkable wall", solid=True, transparent=False)
door_closed = Tile('+', "closed door", "an unremarkable door", solid=True, transparent=False)
door_open = Tile(',', "open door", "an unremarkable door", solid=False, transparent=True)
w = c.initscr()
c.curs_set(0)
c.raw()
c.echo(False)
wld = World(w, 80, 23, floor)
drunk = Drunkard("drunkard")
db = Body("drunkard", 'H', "A smelly drunkard, stumbling about.", c.COLOR_WHITE)
drunk.incarnate(db)
db.world = wld
drunk.world = wld
db.x = 20
db.y = 16
wld.behaviors = [p, drunk]
wld.bodies = [pb, db]
pb.world = wld
p.world = wld
pb.x = 3
pb.y = 6
wld.set(12, 12, wall)
wld.set(13, 12, wall)
wld.set(14, 12, wall)
wld.set(15, 12, wall)
wld.set(16, 12, wall)
wld.set(16, 13, wall)
wld.set(16, 14, wall)
wld.set(18, 12, wall)
wld.set(18, 13, wall)
wld.set(18, 14, wall)
wld.set(12, 13, door_closed)
while wld.run:
for behavior in wld.behaviors:
behavior.behave()
c.endwin()
game.run()

274
william.scm Normal file
View File

@ -0,0 +1,274 @@
(import socket)
(import matchable)
(import comparse)
(import (chicken format))
(define null '())
(define void
(constantly null))
(define (blocking-socket-receive sck bytes)
(condition-case (socket-receive sck bytes)
((exn timeout) (blocking-socket-receive sck bytes))))
(define (cell a)
(letrec* ((self (lambda args
(if (zero? (length args))
a
(begin
(set! a (car args))
self)))))
self))
(define (generator state get set)
(let ((state-cell (cell state)))
(lambda args
(if (zero? (length args))
(get state-cell)
(set state-cell (car args))))))
(define (curry fn a)
(lambda (b)
(fn a b)))
(define (output str)
(display str)
(newline))
(define (string-split chr str)
(let loop ((r (list)) (ln (string->list str)))
(if (null? ln)
(cons str #f)
(if (eq? chr (car ln))
(cons (list->string (reverse r)) (list->string (cdr ln)))
(loop (cons (car ln) r) (cdr ln))))))
(define (string-split-every chr str)
(let ((r (string-split chr str)))
(if (cdr r)
(cons (car r) (string-split-every chr (cdr r)))
(list (car r)))))
(define (line-buffered-socket sck)
(generator ""
(lambda (buffer)
(let loop ()
(let ((input (string-split #\newline
(string-append (buffer)
(blocking-socket-receive sck 256)))))
(let ((line (car input))
(rest (cdr input)))
(if (not rest)
(string-append line (loop))
(begin
(buffer rest)
line))))))
(lambda (buffer str)
(socket-send sck str))))
(define (line-buffered-tcp-connection address port)
(let ((sck (socket af/inet sock/stream)))
(socket-connect sck (inet-address address port))
(line-buffered-socket sck)))
(define (take-while pred? ln)
(let loop ((r (list)) (ln ln))
(if (or (null? ln) (not (pred? (car ln))))
(reverse r)
(loop (cons (car ln) r) (cdr ln)))))
(define (drop-while pred? ln)
(if (or (null? ln) (not (pred? (car ln))))
ln
(drop-while pred? (cdr ln))))
(define (whitespace? chr)
(eq? #\space chr))
(define (colon? chr)
(eq? #\: chr))
(define (invert pred?)
(lambda (x)
(not (pred? x))))
(define (empty-string? str)
(equal? "" str))
(define (filter pred? ln)
(let loop ((r (list)) (ln ln))
(if (null? ln)
(reverse r)
(loop (if (pred? (car ln))
(cons (car ln) r)
r) (cdr ln)))))
(define (first-letter str)
(car (string->list str)))
;; lift fn into the parser
(define (lift fn parser)
(bind parser (compose result fn)))
(define parse-anything
(satisfies (constantly #t)))
(define rest-of-tokens
(lift list->string (zero-or-more parse-anything)))
(define (is-not t)
(satisfies (compose not (curry eqv? t))))
(define (not-in ln)
(satisfies (lambda (e)
(not (memq e ln)))))
(define parse-word
(lift list->string (one-or-more (is-not #\space))))
;; parse p, then consume and skip tokens using term
(define (followed-by-consuming p term)
(lift car (sequence p (maybe (skip term) #t))))
(define parse-prefix
(preceded-by (is #\:) (any-of (lift list->string (followed-by-consuming (followed-by (one-or-more (not-in '(#\space #\!))) (is #\!)) parse-word)) parse-word)))
(define rest-of-tokens
(lift list->string (zero-or-more (satisfies (constantly #t)))))
(define parse-comma-string
(preceded-by (is #\:) rest-of-tokens))
(define whitespace
(one-or-more (is #\space)))
(define (separated-by p1 sep p2)
(sequence (followed-by p1 sep) (preceded-by sep p2)))
(define (parse-separated-list p sep)
(lift flatten (any-of (separated-by p sep (recursive-parser (parse-separated-list p sep))) p)))
(define parse-suffix
(preceded-by (is #\:) rest-of-tokens))
(define parse-irc
(lift flatten (separated-by (any-of parse-prefix parse-word)
whitespace
(parse-separated-list (any-of parse-suffix parse-word)
whitespace))))
(define tokenize-tell-command
(lift flatten (separated-by parse-word whitespace (separated-by parse-word whitespace rest-of-tokens))))
(define format-nl
(compose (curry format "~A~%") format))
(define (my-assoc k ln default)
(if (null? ln)
default
(if (equal? k (caar ln))
(cdar ln)
(my-assoc k (cdr ln) default))))
(define (assoc-insert k v ln)
(if (null? ln)
(list (cons k v))
(if (equal? k (caar ln))
(cons (cons k v) (cdr ln))
(cons (car ln) (assoc-insert k v (cdr ln))))))
(define (assoc-delete k ln)
(if (null? ln)
(list)
(if (equal? k (caar ln))
(cdr ln)
(cons (car ln) (assoc-delete k (cdr ln))))))
(define-syntax begin1
(syntax-rules ()
((begin1 first body ...)
(let ((r first))
body ...
r))))
(define-syntax let-over-lambda
(er-macro-transformer
(lambda (exp rename compare)
`(define ,(cadr exp)
(letrec* ((state ,(caddr exp))
(self (lambda args
(define return
(compose (constantly self) state))
(match args
,@(cdddr exp)))))
self)))))
(define-syntax upon-else
(syntax-rules ()
((upon-else exp value else)
(let ((r exp))
(if r
(r value)
else)))))
(let-over-lambda (table kv dv)
(cell kv)
((k) (my-assoc k (state) dv))
((k v) (return (assoc-insert k v (state)))))
(let-over-lambda (accumulator)
(cell null)
(() (begin1
(state)
(state null)))
((e) (return (cons e (state)))))
(let-over-lambda (accumulators kv)
(table kv #f)
((k) ((default void (state k))))
((k v) (upon-else (state k)
v
(return k ((accumulator) v)))))
(define (default d v)
(if v v d))
(define (upon fn v)
(if v (fn v) v))
(define (inline-output str)
(display "DEBUG: ")
(output str)
str)
#;(define (tellbot connection)
(define irc-send
(compose connection inline-output format-nl))
(define messages
(lossy-multicell null #f))
(output "connecting")
(irc-send "USER william william william william")
(irc-send "NICK william")
(output "connected")
(let loop ()
(match (parse parse-irc (inline-output (connection)))
(("PING" ping-string)
(irc-send "PONG ~A" ping-string))
((user "PRIVMSG" target msg)
(let ((stored-messages (messages user)))
(if stored-messages
(begin
(map (curry irc-send "william PRIVMSG #cvbe :~A") stored-messages)
(loop)
(loop)))))
(match (parse tokenize-tell-command msg)
((".tell" target-user tell-message)
(messages target-user tell-message))
(_ (loop)))
(_ (loop)))))
(define (main)
(tellbot (line-buffered-tcp-connection "127.0.0.1" 6667)))
;; (main)