commit cb97b35d4e91b0ef36439cc42a39b0fd2374c0ae Author: Daniel Ziltener Date: Sun Jan 3 18:54:03 2021 +0100 In the beginning there was darkness diff --git a/board.scm b/board.scm new file mode 100644 index 0000000..92839f8 --- /dev/null +++ b/board.scm @@ -0,0 +1,368 @@ +;; -*- geiser-scheme: chicken -*- +(module board + * + (import scheme + (chicken base) + (chicken random) + (chicken plist) + miscmacros + srfi-1 + srfi-123 + mini-kanren + uuid + (prefix sdl2 "sdl2:") + (prefix sdl2-image "img:") + (prefix sdl2-ttf "ttf:")) + + (ttf:init!) + + (define logo-font (ttf:open-font "resources/ui/SourceSerifPro-Regular.otf" 80)) + + + (define background #f) + (define house #f) + (define flower #f) + (define dicesym #f) + (define flower-rotation 0) + (define player-offset '((1 400 . 250) + (2 400 . 835))) + + (define tiles #f) + + (define white-bottom #f) + (define white-top #f) + (define black-bottom #f) + (define black-top #f) + + (define state #f) + + (define orig-board + '(;; Torso + ((0 . 0) . flower:) + ((0 . 1) . gate:) + ((0 . 2) . flower:) + ((1 . 0) . temple:) + ((1 . 1) . water:) + ((1 . 2) . temple:) + ((2 . 0) . water:) + ((2 . 1) . market:) + ((2 . 2) . water:) + ((3 . 0) . temple:) + ((3 . 1) . flower:) + ((3 . 2) . temple:) + ;; Neck + ((4 . 1) . water:) + ((5 . 1) . market:) + ;; Head + ((6 . 0) . flower:) + ((6 . 1) . temple:) + ((6 . 2) . flower:) + ((7 . 0) . treasury:) + ((7 . 1) . water:) + ((7 . 2) . treasury:))) + + (define player-paths + '((1 . ((1 . (3 . 0)) + (2 . (2 . 0)) + (3 . (1 . 0)) + (4 . (0 . 0)) + (5 . (0 . 1)) + (6 . (1 . 1)) + (7 . (2 . 1)) + (8 . (3 . 1)) + (9 . (4 . 1)) + (10 . (5 . 1)) + (11 . (6 . 1)) + (12 . (7 . 1)) + (13 . (7 . 0)) + (14 . (6 . 0)) + (15 . (5 . 0)))) + (2 . ((1 . (3 . 2)) + (2 . (2 . 2)) + (3 . (1 . 2)) + (4 . (0 . 2)) + (5 . (0 . 1)) + (6 . (1 . 1)) + (7 . (2 . 1)) + (8 . (3 . 1)) + (9 . (4 . 1)) + (10 . (5 . 1)) + (11 . (6 . 1)) + (12 . (7 . 1)) + (13 . (7 . 2)) + (14 . (6 . 2)) + (15 . (5 . 2)))))) + + (define (grid-rect x y) + (sdl2:make-rect (+ 500 (* x 120)) + (+ 400 (* y 120)) + 120 120)) + + (define (init-piece player id) + (let ((coords (sdl2:make-rect (+ (car (alist-ref player player-offset)) (* id 100)) + (cdr (alist-ref player player-offset)) 75 75))) + `((uuid: . ,(uuid)) + (player: . ,player) + (state: . top:) + (initial-coords: . ,coords) + (coords: . ,coords) + (target-coords: . ,coords) + (step: . 0)))) + + (define (initialize-state!) + (set! state + `((active-player: . 1) + (players: . ((1 . ((type: . local:) + (state: . begin:) + (piece-y-offset: . -10))) + (2 . ((type: . local:) + (state: . wait:) + (piece-y-offset: . 10))))) + (pieces: . (,(init-piece 1 0) + ,(init-piece 1 1) + ,(init-piece 1 2) + ,(init-piece 1 3) + ,(init-piece 1 4) + ,(init-piece 1 5) + ,(init-piece 1 6) + ,(init-piece 2 0) + ,(init-piece 2 1) + ,(init-piece 2 2) + ,(init-piece 2 3) + ,(init-piece 2 4) + ,(init-piece 2 5) + ,(init-piece 2 6)))))) + + (define (refo coll key val) + (membero (cons key val) coll)) + + (define (field coords type) + (membero (cons coords type) orig-board)) + + ;; When given a piece, returns its board x y position. + ;; When given a board position, returns the piece. + (define (piece-pos piece pos) + (fresh (player piece-step player-path) ; Initialize empty variables + (membero piece (cdr (assoc pieces: state))) ; The piece is a member of the state alist + (refo piece player: player) ; The player number is under key "player:" in the piece alist. + (refo piece step: piece-step) ; The piece step is under key "step:" in the piece alist. + (refo player-paths player player-path) ; The player-path is under the player number in the "player-paths" alist + (=/= piece-step 0) ; The piece step cannot be 0 + (refo player-path piece-step pos))) ; The position is under piece-step in the "player-path" alist. + + ;; Given a piece and a diceroll, returns the board x y position + ;; the piece will have to move to. + (define (piece-targetpos piece dice out) + (fresh (player piece-step piece-targetstep player-path) ; Initialize empty variables + (membero piece (cdr (assoc pieces: state))) ; The piece is a member of the state alist + (refo piece player: player) ; The player number is the value of the piece entry with key "player:" + (refo piece step: piece-step) ; The step number is the value of the piece entry with key "step:" + (numbero piece-step) ; piece-step is a number + (refo player-paths player player-path) ; The played piece path is the value of the player-paths entry with key player + (refo player-path piece-targetstep out) ; Set "out" to the player-path entry found under key piece-targetstep + (project (piece-step) ; Turn piece-step from a logic variable into a usable value... + (== (+ piece-step dice) piece-targetstep)))) ; and set piece-targetstep to the sum of piece-step plus the dice value + + ;; Given a piece and a dice value, returns the actions to be performed on the board. + (define (check-move piece dice out) + (fresh (player piece-uuid target-uuid newpiece-pos target-player target-piece) + (refo piece player: player) + (refo piece uuid: piece-uuid) + (listo out) + (conda ((piece-targetpos piece dice newpiece-pos) ; Given the target would be on the board + (conda ; v Subconditions + ((piece-pos target-piece newpiece-pos) ; | Given there is a piece on the target house + (conda ((refo target-piece player: player) ; | It's the player's faction + (membero (cons block: #t) out)) ; | | => Deny the movement + ((refo target-piece uuid: target-uuid) ; | It's the enemy faction + (conda ((field newpiece-pos flower:) ; | | Given the piece would end up on flower + (membero (cons block: #t) out)) ; | | | => Deny the movement + ; | | Else: yeet the piece back to start + ((membero (cons reset: target-uuid) out) ; | | | => Reset the enemy piece + (membero (cons move: piece-uuid) out)))))); | | | => Move the player piece + ; | Else: The target house is clear + ((conda ((field newpiece-pos flower:) ; | | Given the piece would end up on flower + (membero (cons move: piece-uuid) out) ; | | | => Move the piece + (membero (cons state: (cons player begin:)) out)) ; | | | => Set the state so the dice can be rolled again + ((membero (cons move: piece-uuid) out)))) ; | | Else: move the piece + ((membero (cons move: piece-uuid) out)))) ; | => Move the player piece + ; Else: Target would be off board + ((membero (cons block: #t) out))))) ; | => Deny the movement + + (define (check-can-player-move player dice out) + (fresh (piece commands) ; Initialize empty variables + (membero piece (cdr (assoc pieces: state))) ; The piece is a member of the state list + (refo piece player: player) ; It belongs to the active player + (check-move piece dice commands) ; Determine of the piece can move given the dice roll + (conda ((membero (cons block: #t) commands) ; Given the call to "check-move" returns a blocking command + (== out #f)) ; | Return false + ((== out #t))))) ; Else: return true + + (define (load-texture renderer file) + (sdl2:create-texture-from-surface renderer (img:load file))) + + (define (prepare! renderer) + (set! flower (load-texture renderer "resources/tiles/flower.png")) + (set! dicesym (load-texture renderer "resources/sprites/die0.png")) + (set! tiles + `((flower: . ,(load-texture renderer "resources/tiles/flower.png")) + (gate: . ,(load-texture renderer "resources/tiles/gate.png")) + (water: . ,(load-texture renderer "resources/tiles/water.png")) + (temple: . ,(load-texture renderer "resources/tiles/temple.png")) + (treasury: . ,(load-texture renderer "resources/tiles/treasury.png")) + (market: . ,(load-texture renderer "resources/tiles/market.png")))) + (set! background (load-texture renderer "resources/ui/gate.jpeg")) + (set! house (load-texture renderer "resources/tiles/house.png")) + + (set! white-bottom (load-texture renderer "resources/sprites/piece-white-bottom.png")) + (set! white-top (load-texture renderer "resources/sprites/piece-white-top.png")) + (set! black-bottom (load-texture renderer "resources/sprites/piece-black-bottom.png")) + (set! black-top (load-texture renderer "resources/sprites/piece-black-top.png")) + (initialize-state!) + #f) + + (define (find-piece-for-uuid uuid) + (find (lambda (piece) + (eq? uuid (alist-ref uuid: piece))) + (alist-ref pieces: state))) + + (define (reset-piece! piece-uuid) + (let ((piece (find-piece-for-uuid piece-uuid))) + (print "Reset piece " piece) + (set-cdr! (assoc step: piece) 0) + (set-cdr! (assoc coords: piece) (alist-ref initial-coords: piece)))) + + (define (move-piece! piece-uuid steps) + (let ((piece (find-piece-for-uuid piece-uuid))) + (print "Move piece " piece) + (let* ((active-player (alist-ref active-player: state)) + (players (alist-ref players: state)) + (player (alist-ref active-player players)) + (piece-y-offset (alist-ref piece-y-offset: player)) + (new-step (if (< (alist-ref step: piece) 15) + (+ steps (alist-ref step: piece)) + (alist-ref step: piece))) + (player-path (alist-ref active-player player-paths)) + (coords (alist-ref new-step player-path)) + (rect (grid-rect (car coords) (cdr coords)))) + (set! (sdl2:rect-x rect) (+ (sdl2:rect-x rect) 20)) + (set! (sdl2:rect-y rect) (+ (sdl2:rect-y rect) 20 piece-y-offset)) + (set! (sdl2:rect-w rect) 75) + (set! (sdl2:rect-h rect) 75) + (set-cdr! (assoc step: piece) new-step) + (set-cdr! (assoc coords: piece) rect) + (set-cdr! (assoc active-player: state) (if (eq? 1 active-player) 2 1))))) + + (define (check-piececlick) + (let/cc break + (let* ((active-player (alist-ref active-player: state)) + (piece (find (lambda (x) + (and (sdl2:point-in-rect? (get 'sdlprops 'mouse-point) (alist-ref coords: x)) + (eq? (alist-ref player: x) active-player))) + (alist-ref pieces: state))) + (piece (if (eqv? #f piece) (break #t) piece)) ;; Jump out if no piece clicked. + (pos (alist-ref step: piece)) + (dice 1) + (instructions (car (run 1 (q) (check-move piece dice q))))) + (for-each + (lambda (instruction) + (let ((inst (car instruction)) + (arg (cdr instruction))) + (case inst + ((block:) #t) + ((reset:) (reset-piece! arg)) + ((move:) (move-piece! arg dice))))) + instructions) + ;; (for-each + ;; (lambda (piece) + ;; (when (and (sdl2:point-in-rect? (get 'sdlprops 'mouse-point) (alist-ref coords: piece)) + ;; (eq? (alist-ref player: piece) + ;; active-player)) + ;; (move-piece! piece 1))) + ;; (alist-ref pieces: state)) + ))) + + (define (handle-event ev) + (case (sdl2:event-type ev) + ((mouse-button-up) + (check-piececlick)))) + + (define (update-scene!) + (set! flower-rotation (modulo (ceiling (/ (get 'sdlprops 'ticks) 50)) + 360)) + #f) + + (define (render-logo! window) + (let*-values (((text-w text-h) (ttf:size-utf8 logo-font "The Royal Game of Ur"))) + (sdl2:render-copy-ex! window flower + #f (sdl2:make-rect 50 50 100 100) flower-rotation) + (sdl2:render-copy-ex! window flower + #f (sdl2:make-rect 1770 50 100 100) flower-rotation) + (sdl2:render-copy! window + (sdl2:create-texture-from-surface window + (ttf:render-utf8-blended logo-font "The Royal Game of Ur" (sdl2:make-color 0 0 0))) + #f (sdl2:make-rect (- (/ 1920 2) (/ text-w 2)) 10 text-w text-h)) + )) + + (define (render-field! renderer type x y) + (let* ((rect (grid-rect x y)) + (tilerect (sdl2:make-rect (+ 10 (sdl2:rect-x rect)) + (+ 10 (sdl2:rect-y rect)) + 100 100))) + (sdl2:render-copy! renderer house #f rect) + (sdl2:render-copy! renderer (alist-ref type tiles) #f tilerect))) + + (define (render-dice! renderer) + (sdl2:render-copy! renderer dicesym #f (sdl2:make-rect 1600 700 75 75))) + + (define (draw-orig-board! renderer) + (sdl2:render-draw-colour-set! renderer (sdl2:make-colour 0 0 0 0)) + ;; Board + (for-each (lambda (field) + (render-field! renderer (cdr field) (caar field) (cdar field))) + orig-board) + ;; Outline + ;; Left border torso + (sdl2:render-fill-rect! renderer (sdl2:make-rect 495 400 10 (* 120 3))) + ;; Top border torso + (sdl2:render-fill-rect! renderer (sdl2:make-rect 495 395 (+ 10 (* 120 4)) 10)) + ;; Bottom border torso + (sdl2:render-fill-rect! renderer (sdl2:make-rect 495 755 (+ 10 (* 120 4)) 10)) + ;; Right upper border torso + (sdl2:render-fill-rect! renderer (sdl2:make-rect 975 395 10 (+ 10 120))) + ;; Right lower border torso + (sdl2:render-fill-rect! renderer (sdl2:make-rect 975 635 10 (+ 10 120))) + ;; Top border neck + (sdl2:render-fill-rect! renderer (sdl2:make-rect 975 515 (+ 10 (* 120 2)) 10)) + ;; Bottom border neck + (sdl2:render-fill-rect! renderer (sdl2:make-rect 975 635 (+ 10 (* 120 2)) 10)) + ;; Left upper border head + (sdl2:render-fill-rect! renderer (sdl2:make-rect 1215 395 10 (+ 10 120))) + ;; Left lower border head + (sdl2:render-fill-rect! renderer (sdl2:make-rect 1215 635 10 (+ 10 120))) + ;; Top border head + (sdl2:render-fill-rect! renderer (sdl2:make-rect 1215 395 (+ 10 (* 120 2)) 10)) + ;; Bottom border head + (sdl2:render-fill-rect! renderer (sdl2:make-rect 1215 755 (+ 10 (* 120 2)) 10)) + ;; Right border head + (sdl2:render-fill-rect! renderer (sdl2:make-rect 1455 395 10 (+ 10 (* 120 3))))) + + (define (draw-pieces! renderer) + (for-each (lambda (piece) + (sdl2:render-copy! renderer + (if (eq? 1 (alist-ref player: piece)) + (if (eq? top: (alist-ref state: piece)) + black-top black-bottom) + (if (eq? top: (alist-ref state: piece)) + white-top white-bottom)) + #f (alist-ref coords: piece))) + (alist-ref pieces: state))) + + (define (draw-scene! renderer) + (sdl2:render-copy! renderer background) + (render-logo! renderer) + (draw-orig-board! renderer) + (draw-pieces! renderer) + (render-dice! renderer) + ) + ) diff --git a/main.scm b/main.scm new file mode 100644 index 0000000..7c3546c --- /dev/null +++ b/main.scm @@ -0,0 +1,91 @@ +;; -*- geiser-scheme: chicken -*- +(include "menu.scm") +(include "board.scm") + +(import scheme + (chicken base) + (chicken plist) + (chicken condition) + (chicken format) + (prefix sdl2 "sdl2:") + (prefix sdl2-image "img:") + (prefix sdl2-ttf "ttf:") + (prefix menu "menu:") + (prefix board "board:") + miscmacros) + +(sdl2:set-main-ready!) +(sdl2:init! '(video timer events)) +(ttf:init!) +(sdl2:set-hint! 'render-scale-quality "best") + +(on-exit sdl2:quit!) +(current-exception-handler + (let ((original-handler (current-exception-handler))) + (lambda (exception) + (sdl2:quit!) + (original-handler exception)))) + +(define window (sdl2:create-window! "The Royal Game of Alnothur" 'centered 'centered 1920 1080 '(opengl))) +(define renderer (sdl2:create-renderer! window -1 '(accelerated target-texture))) + +(sdl2:render-draw-colour-set! renderer (sdl2:make-colour 128 128 128 0)) +(sdl2:render-fill-rect! renderer (sdl2:make-rect 0 0 1920 1080)) +(sdl2:delay! 10) + +(put! 'sdlprops 'mouse-point (sdl2:make-point 0 0)) +(put! 'sdlprops 'old-ticks (sdl2:get-ticks)) + +(put! 'progprops 'current-state #f) +(put! 'progprops 'next-state menu:) + +(define (draw-scene!) + (when (not (equal? (get 'progprops 'current-state) + (get 'progprops 'next-state))) + (put! 'progprops 'current-state (get 'progprops 'next-state)) + (sdl2:render-draw-colour-set! renderer (sdl2:make-colour 128 128 128 0)) + (sdl2:render-fill-rect! renderer (sdl2:make-rect 0 0 1920 1080)) + (case (get 'progprops 'next-state) + ((menu:) (menu:prepare! renderer)) + ((board:) (board:prepare! renderer)))) + + (case (get 'progprops 'current-state) + ((menu:) (menu:draw-scene! renderer)) + ((board:) (board:draw-scene! renderer))) + (sdl2:render-present! renderer)) + +(define (update-scene!) + (case (get 'progprops 'current-state) + ((menu:) (menu:update-scene!)) + ((board:) (board:update-scene!)))) + +(define (handle-event ev exit-main-loop!) + (case (sdl2:event-type ev) + ((window) (draw-scene!)) + ((quit) (exit-main-loop! #t)) + ((mouse-motion) + (put! 'sdlprops 'mouse-x (sdl2:mouse-motion-event-x ev)) + (put! 'sdlprops 'mouse-y (sdl2:mouse-motion-event-y ev)) + (put! 'sdlprops 'mouse-point (sdl2:make-point (get 'sdlprops 'mouse-x) (get 'sdlprops 'mouse-y)))) + ((key-down) + (case (sdl2:keyboard-event-sym ev)) + (draw-scene!))) + (case (get 'progprops 'current-state) + ((menu:) (menu:handle-event ev)) + ((board:) (board:handle-event ev)))) + +(let/cc exit-main-loop! + (while #t + (sdl2:pump-events!) + (while (sdl2:has-events?) + (handle-event (sdl2:poll-event!) exit-main-loop!)) + (put! 'sdlprops 'ticks (sdl2:get-ticks)) + (put! 'sdlprops 'tickdelta (- (get 'sdlprops 'ticks) + (get 'sdlprops 'old-ticks))) + (draw-scene!) + (update-scene!) + (put! 'sdlprops 'old-ticks (get 'sdlprops 'ticks)) + (sdl2:delay! 10))) + +(sdl2:destroy-renderer! renderer) +(sdl2:quit!) diff --git a/menu.scm b/menu.scm new file mode 100644 index 0000000..9a896da --- /dev/null +++ b/menu.scm @@ -0,0 +1,105 @@ +;; -*- geiser-scheme: chicken -*- +(module menu + * + (import scheme + (chicken base) + (chicken plist) + srfi-1 + (prefix sdl2 "sdl2:") + (prefix sdl2-image "img:") + (prefix sdl2-ttf "ttf:")) + + (ttf:init!) + + (define logo-font (ttf:open-font "resources/ui/SourceSerifPro-Regular.otf" 80)) + (define button-font (ttf:open-font "resources/ui/SourceSerifPro-Regular.otf" 50)) + + (define (render-button renderer text) + (let*-values (((button) (img:load "resources/ui/button.png")) + ((button-hover) (img:load "resources/ui/button-hover.png")) + ((button-w) (sdl2:surface-w button)) + ((button-h) (sdl2:surface-h button)) + ((text-w text-h) (ttf:size-utf8 button-font text)) + ((text-x) (round (- (/ button-w 2) (/ text-w 2)))) + ((text-y) (round (- (/ button-h 2) (/ text-h 2))))) + (sdl2:blit-surface! + (ttf:render-utf8-blended button-font text (sdl2:make-color 0 0 0)) #f + button + (sdl2:make-rect text-x text-y text-w text-h)) + (sdl2:blit-surface! + (ttf:render-utf8-blended button-font text (sdl2:make-color 0 0 0)) #f + button-hover + (sdl2:make-rect text-x text-y text-w text-h)) + (list (cons surface: (sdl2:create-texture-from-surface renderer button)) + (cons surface-hover: (sdl2:create-texture-from-surface renderer button-hover)) + (cons width: button-w) + (cons height: button-h)))) + + (define (make-button renderer text offset-x offset-y on-click) + (let* ((blist (render-button renderer text)) + (blist (alist-cons rect: (sdl2:make-rect offset-x offset-y + (cdr (assoc width: blist)) + (cdr (assoc height: blist))) blist)) + (blist (alist-cons offset-x: offset-x blist)) + (blist (alist-cons offset-y: offset-y blist)) + (blist (alist-cons on-click: on-click blist))) + blist)) + + (define background #f) + (define flower #f) + (define flower-rotation 0) + (define buttons #f) + + (define (prepare! renderer) + (set! background (sdl2:create-texture-from-surface renderer (img:load "resources/ui/zikkurat.png"))) + (set! flower (sdl2:create-texture-from-surface renderer (img:load "resources/tiles/flower.png"))) + (set! buttons (list (make-button renderer "Test" 650 300 (lambda () (put! 'progprops 'next-state board:))) + (make-button renderer "Test 2" 650 400 (lambda () (print "Button Test 2 clicked")))))) + + (define (check-buttonclick) + (for-each + (lambda (button) + (if (sdl2:point-in-rect? (get 'sdlprops 'mouse-point) (cdr (assoc rect: button))) + ((cdr (assoc on-click: button))))) + buttons)) + + (define (handle-event ev) + (case (sdl2:event-type ev) + ((mouse-button-up) + (check-buttonclick)))) + + (define (render-logo! window) + (let*-values (((text-w text-h) (ttf:size-utf8 logo-font "The Royal Game of Ur"))) + (sdl2:render-copy-ex! window flower + #f (sdl2:make-rect 50 50 100 100) flower-rotation) + (sdl2:render-copy-ex! window flower + #f (sdl2:make-rect 1770 50 100 100) flower-rotation) + (sdl2:render-copy! window + (sdl2:create-texture-from-surface window + (ttf:render-utf8-blended logo-font "The Royal Game of Ur" (sdl2:make-color 0 0 0))) + #f (sdl2:make-rect (- (/ 1920 2) (/ text-w 2)) 10 text-w text-h)) + )) + + (define (update-scene!) + (set! flower-rotation (modulo (ceiling (/ (get 'sdlprops 'ticks) 50)) + 360))) + + (define (draw-scene! window) + ;; Background + (sdl2:render-copy! window background) + + ;; Logo + (render-logo! window) + + ;; Buttons + (for-each + (lambda (button) + (sdl2:render-copy! window + (if (sdl2:point-in-rect? (get 'sdlprops 'mouse-point) (cdr (assoc rect: button))) + (cdr (assoc surface-hover: button)) (cdr (assoc surface: button))) #f + (sdl2:make-rect (cdr (assoc offset-x: button)) + (cdr (assoc offset-y: button)) + (cdr (assoc width: button)) + (cdr (assoc height: button))))) + buttons) + )) diff --git a/resources/drawingboard.svg b/resources/drawingboard.svg new file mode 100644 index 0000000..acb1515 --- /dev/null +++ b/resources/drawingboard.svg @@ -0,0 +1,1050 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/ui/SourceSerifPro-Regular.otf b/resources/ui/SourceSerifPro-Regular.otf new file mode 100644 index 0000000..ad044c7 Binary files /dev/null and b/resources/ui/SourceSerifPro-Regular.otf differ diff --git a/resources/ui/gate.jpeg b/resources/ui/gate.jpeg new file mode 100644 index 0000000..a919cff Binary files /dev/null and b/resources/ui/gate.jpeg differ diff --git a/resources/ui/zikkurat.png b/resources/ui/zikkurat.png new file mode 100644 index 0000000..c43044a Binary files /dev/null and b/resources/ui/zikkurat.png differ