william tell
This commit is contained in:
parent
096fd91378
commit
447b9622a2
@ -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
|
||||
|
148
rougelike.py
148
rougelike.py
@ -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
274
william.scm
Normal 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)
|
Loading…
Reference in New Issue
Block a user