william tell
This commit is contained in:
parent
096fd91378
commit
447b9622a2
@ -1,4 +1,4 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
#xrdb -merge ~/.Xresources.green
|
#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
|
#xrdb -merge ~/.Xresources
|
||||||
|
|||||||
148
rougelike.py
148
rougelike.py
@ -7,6 +7,56 @@ from time import sleep
|
|||||||
from grid import Grid, bresenhams
|
from grid import Grid, bresenhams
|
||||||
from fov import fieldOfView
|
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():
|
class Tile():
|
||||||
def __init__(self, glyph, name, description, solid=False, transparent=True, color=c.COLOR_WHITE):
|
def __init__(self, glyph, name, description, solid=False, transparent=True, color=c.COLOR_WHITE):
|
||||||
self.appearance = glyph
|
self.appearance = glyph
|
||||||
@ -23,15 +73,12 @@ class Tile():
|
|||||||
return self.description
|
return self.description
|
||||||
|
|
||||||
class World(Grid):
|
class World(Grid):
|
||||||
def __init__(self, window, width, height, initial_tile):
|
def __init__(self, width, height, initial_tile):
|
||||||
super().__init__(width, height, initial_tile)
|
super().__init__(width, height, initial_tile)
|
||||||
self.run = True
|
self.run = True
|
||||||
self.window = window
|
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
|
|
||||||
self.bodies = []
|
self.bodies = []
|
||||||
self.behavior = []
|
|
||||||
|
|
||||||
class Behaviour():
|
class Behaviour():
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
@ -130,7 +177,7 @@ class Player(Behaviour):
|
|||||||
else:
|
else:
|
||||||
self.message("You see nothing here to close.")
|
self.message("You see nothing here to close.")
|
||||||
case 'q':
|
case 'q':
|
||||||
self.world.run = False
|
game.world.run = False
|
||||||
case 'r':
|
case 'r':
|
||||||
if self.realtime:
|
if self.realtime:
|
||||||
self.realtime = False
|
self.realtime = False
|
||||||
@ -156,15 +203,15 @@ class Drunkard(Behaviour):
|
|||||||
self.body.move((dx, dy))
|
self.body.move((dx, dy))
|
||||||
|
|
||||||
class Body():
|
class Body():
|
||||||
def __init__(self, name, appearence, description, color):
|
def __init__(self, name, appearence, description, color, world, x, y):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.appearence = appearence
|
self.appearence = appearence
|
||||||
self.description = description
|
self.description = description
|
||||||
self.color = color
|
self.color = color
|
||||||
self.behavior = None
|
self.behavior = None
|
||||||
self.world = None
|
self.world = world
|
||||||
self.x = None
|
self.x = x
|
||||||
self.y = None
|
self.y = y
|
||||||
|
|
||||||
def move(self, direction):
|
def move(self, direction):
|
||||||
x, y = direction
|
x, y = direction
|
||||||
@ -212,19 +259,39 @@ class Body():
|
|||||||
self.world.window.addch(self.y, self.x, self.appearence)
|
self.world.window.addch(self.y, self.x, self.appearence)
|
||||||
|
|
||||||
class Conversation(list):
|
class Conversation(list):
|
||||||
def __init__(self, title, description):
|
def __init__(self, window, title, description):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.description = description
|
self.description = description
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# rendering code goes here
|
valid_responses = filter(lambda r: r.prerequisite() if r.prerequisite else True, self)
|
||||||
pass
|
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():
|
class Response():
|
||||||
def __init__(self, name, text, target=None, prerequisite=None, function=None):
|
def __init__(self, name, text, target=None, prerequisite=None, function=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.text = text
|
self.text = text
|
||||||
self.target = target
|
self.target = target
|
||||||
|
self.prerequisite = prerequisite
|
||||||
self.function = function
|
self.function = function
|
||||||
|
|
||||||
def respond(self, title, description):
|
def respond(self, title, description):
|
||||||
@ -234,59 +301,4 @@ class Response():
|
|||||||
if target:
|
if target:
|
||||||
target.run()
|
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.")
|
game.run()
|
||||||
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()
|
|
||||||
|
|||||||
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