Ship layout, missing room descriptions

main
Ashelyn Dawn 4 years ago
parent ced467289b
commit 13ff0dcf44

@ -1,4 +1,4 @@
import React from 'react'
import React, {useEffect} from 'react'
import ReactMarkdown from 'react-markdown'
import useGameState from '../../hooks/useGameState'
@ -16,6 +16,11 @@ export default function Map() {
const [currentFloor, setFloor] = useSharedState('mapFloor', isOnLower ? 'lower' : 'upper')
const [roomName, setRoom] = useSharedState('mapRoom')
// On first render, update room
useEffect(() => {
setRoom(playerLocation)
}, []) // eslint-disable-line
const currentRoom = (roomName && gameState.rooms.get(roomName)) || null
return (
@ -47,7 +52,9 @@ export default function Map() {
{currentRoom ? (
<>
<h3>{currentRoom.printableName}</h3>
<ReactMarkdown>{currentRoom.description}</ReactMarkdown>
{currentRoom.visited
? <ReactMarkdown>{currentRoom.description}</ReactMarkdown>
: <p>Visit this room to unlock its description</p>}
</>
) : (
<h3 style={{marginTop: '45%', textAlign: 'center'}}>Select a Room</h3>

@ -76,10 +76,3 @@
.output.noMouse {
pointer-events: none;
}
/**
* Shadow
*/
.playArea {
}

@ -1,5 +1,5 @@
import {enableMapSet, createDraft, finishDraft, Draft} from 'immer'
import GameState, { GameObject, Room, Door, Item, ObjectType } from './types/GameState'
import GameState, { GameObject, Room, Door, Item, ObjectType, ObjectID, Direction } from './types/GameState'
import ParsedCommand, { ValidCommandDetails, InvalidCommandDetails } from './types/ParsedCommand'
import { GameEventMessage, GameEventCommand } from './types/GameEvent'
@ -20,7 +20,8 @@ export default class Game {
doors: new Map(),
items: new Map(),
player: {location: ''},
messages: []
messages: [],
properties: new Map()
}
private draft : Draft<GameState> | null = null
@ -28,12 +29,12 @@ export default class Game {
constructor() {
let state = this.getState()
state.directions.set('north', {type: ObjectType.Direction, name: 'north', printableName: 'north', aliases: ['n']})
state.directions.set('east', {type: ObjectType.Direction, name: 'east', printableName: 'east', aliases: ['e']})
state.directions.set('south', {type: ObjectType.Direction, name: 'south', printableName: 'south', aliases: ['s']})
state.directions.set('west', {type: ObjectType.Direction, name: 'west', printableName: 'west', aliases: ['w']})
state.directions.set('up', {type: ObjectType.Direction, name: 'up', printableName: 'up', aliases: ['u']})
state.directions.set('down', {type: ObjectType.Direction, name: 'down', printableName: 'down', aliases: ['d']})
state.directions.set('fore', {type: ObjectType.Direction, name: 'fore', printableName: 'fore', aliases: ['north', 'f', 'n'], opposite: 'aft'})
state.directions.set('starboard', {type: ObjectType.Direction, name: 'starboard', printableName: 'starboard', aliases: ['starboard', 'sb', 'e'], opposite: 'port'})
state.directions.set('aft', {type: ObjectType.Direction, name: 'aft', printableName: 'aft', aliases: ['aft', 'a', 's'], opposite: 'fore'})
state.directions.set('port', {type: ObjectType.Direction, name: 'port', printableName: 'port', aliases: ['port', 'p', 'w'], opposite: 'starboard'})
state.directions.set('up', {type: ObjectType.Direction, name: 'up', printableName: 'up', aliases: ['u'], opposite: 'down'})
state.directions.set('down', {type: ObjectType.Direction, name: 'down', printableName: 'down', aliases: ['d'], opposite: 'up'})
this.saveDraft()
}
@ -115,19 +116,96 @@ export default class Game {
.find(room => room.name === state.player.location) || null
}
addRoom(room : Room) {
createProperty(key : string, value : any) {
let state = this.getState()
if(state.properties.has(key))
throw new Error(`Game prop ${key} has already been defined`)
state.properties.set(key, value)
}
setProperty(key : string, value : any) {
let state = this.getState()
if(!state.properties.has(key))
throw new Error(`Game prop ${key} has not been defined`)
state.properties.set(key, value)
}
getProperty(key : string) : any {
let state = this.getState()
if(!state.properties.has(key))
throw new Error(`Game prop ${key} has not been defined`)
return state.properties.get(key)
}
addRoom(name : string, printableName : string | null, description : string) : Draft<Room> {
let room : Room = {
type: ObjectType.Room,
name, aliases: [], printableName: printableName || name, description,
neighbors: new Map(),
visited: false
}
let state = this.getState()
state.rooms.set(room.name, room)
return room
}
addDoor(door: Door) {
addDoor(name : string, description : string) : Draft<Door> {
let door : Door = {
type: ObjectType.Door,
name, aliases: [], printableName: name, description,
neighbors: new Map(),
locked: false,
key: null,
open: false
}
let state = this.getState()
state.doors.set(door.name, door)
return door
}
addItem(item: Item) {
addItem(name : string, description : string, location : string) : Draft<Item> {
let item : Item = {
type: ObjectType.Item,
name, aliases: [], printableName: name, description,
location
}
let state = this.getState()
state.items.set(item.name, item)
return item
}
/**
* Sets up a neighbor relationship such that Room B is [direction] of Room A,
* and Room A is [opposite] of Room B
*
* @param roomA
* @param direction
* @param roomB
*/
setNeighbor(roomA : ObjectID, direction: ObjectID, roomB : ObjectID) {
let a = (this.findObjectByName(roomA, ObjectType.Room) || this.findObjectByName(roomA, ObjectType.Door)) as Room
let b = (this.findObjectByName(roomB, ObjectType.Room) || this.findObjectByName(roomB, ObjectType.Door)) as Room
let dir = this.findObjectByName(direction, ObjectType.Direction) as Direction
if(!a) throw new Error(`No such room or door ${roomA}`)
if(!b) throw new Error(`No such room or door ${roomB}`)
if(!dir) throw new Error(`No such direction ${direction}`)
const opposite = dir.opposite!
a.neighbors.set(direction, b.name)
b.neighbors.set(opposite, a.name)
}
findObjectByName(name : string | undefined | null, type : ObjectType) : GameObject | null {

@ -8,7 +8,8 @@ type GameState = {
readonly player: {
readonly location: ObjectID
}
readonly messages: GameEvent []
readonly messages: GameEvent [],
readonly properties: Map<string, any>
}
export default GameState
@ -20,7 +21,7 @@ export enum ObjectType {
Direction = 'direction'
}
type ObjectID = string
export type ObjectID = string
export type GameObject = {
readonly type : ObjectType,
@ -31,19 +32,21 @@ export type GameObject = {
}
export type Direction = GameObject & {
readonly type : ObjectType.Direction
readonly type : ObjectType.Direction,
readonly opposite? : ObjectID
}
export type Room = GameObject & {
readonly type : ObjectType.Room,
readonly neighbors : Map<ObjectID, ObjectID>
readonly neighbors : Map<ObjectID, ObjectID>,
readonly visited : boolean
}
export type Door = GameObject & {
readonly type : ObjectType.Door,
readonly neighbors : Map<ObjectID, ObjectID>,
readonly locked : boolean,
readonly key : ObjectID,
readonly key : ObjectID | null,
readonly open: boolean
}

@ -1,96 +1,15 @@
import {game, renderer} from './engine/'
import { ObjectType, Room, Door } from './engine/types/GameState'
import {game, rules, renderer} from './engine/'
const entry : Room = {
type: ObjectType.Room,
name: 'entry',
printableName: 'entry',
aliases: [],
neighbors: new Map(),
description: 'A tight corridor with yellow faded walls.'
}
import './rooms.tsx'
const closet : Room = {
type: ObjectType.Room,
name: 'closet',
printableName: 'closet',
aliases: [],
neighbors: new Map(),
description: 'A small closet'
}
const door : Door = {
type: ObjectType.Door,
name: 'door',
printableName: 'white door',
aliases: ['white door'],
neighbors: new Map(),
locked: true,
key: 'brass key',
description: 'A large white door with but a single keybole.',
open: false
}
const office : Room = {
type: ObjectType.Room,
name: 'office',
printableName: 'office',
aliases: [],
neighbors: new Map(),
description: 'An opulent office'
}
entry.neighbors.set('east', 'door')
office.neighbors.set('west', 'door')
door.neighbors.set('east', 'office')
door.neighbors.set('west', 'entry')
entry.neighbors.set('west', 'closet')
closet.neighbors.set('east', 'entry')
game.addRoom(entry)
game.addRoom(office)
game.addRoom(closet)
game.addDoor(door)
game.addItem({
type: ObjectType.Item,
printableName: 'brass key',
name: 'brass key',
aliases: ['key'],
location: 'entry'
})
game.addItem({
type: ObjectType.Item,
printableName: 'gem',
name: 'ruby',
aliases: ['gem'],
location: 'office'
})
game.addItem({
type: ObjectType.Item,
printableName: 'teddy bear',
name: 'teddy',
aliases: ['teddy bear'],
location: 'entry'
})
game.addRoom({
type: ObjectType.Room,
printableName: 'Crew Cabin',
name: 'cabin',
aliases: [],
neighbors: new Map(),
description: `
A dark and dingy room with a single bunk bed along the starboard side.
game.getState().player.location = 'cabin'
game.getCurrentRoom()!.visited = true
The washroom is to the aft, with the common room to port.
`
rules.onAfterCommand((command, game) => {
game.getCurrentRoom()!.visited = true
})
game.getState().player.location = 'cabin'
game.saveDraft()

@ -0,0 +1,38 @@
import {game} from './engine'
game.addRoom('cabin', 'Crew Cabin', `
A dark and dingy room with a single bunk bed along the starboard side.
The washroom is to the aft, with the common room to port.
`)
game.addRoom('bathroom', 'Washroom', `
Tight, cramped, but serviceable. This ship was really only meant for a crew
of one or two, and that is no more evident than here.
A barren metal bowl sits below a cracked mirror and above a small cupboard.
`)
// TODO: Room descriptions
game.addRoom('commons', 'Common Room', `// TODO`)
game.addRoom('bridge', 'Bridge', `// TODO`)
game.addRoom('medbay', 'Medical Bay', `// TODO`)
game.addRoom('stairupper', 'Upper Stairwell', `// TODO`)
game.addRoom('stairlower', 'Lower Stairwell', `// TODO`)
game.addRoom('mainframe', 'Mainframe', `// TODO`)
game.addRoom('engine', 'Engine Room', `// TODO`)
game.addRoom('docking', 'Docking Bay', `// TODO`)
// Regular hallways
game.setNeighbor('cabin', 'aft', 'bathroom')
game.setNeighbor('cabin', 'port', 'commons')
game.setNeighbor('commons', 'port', 'medbay')
game.setNeighbor('commons', 'fore', 'bridge')
game.setNeighbor('medbay', 'aft', 'stairupper')
game.setNeighbor('stairupper', 'down', 'stairlower')
game.setNeighbor('stairlower', 'fore', 'mainframe')
game.setNeighbor('mainframe', 'starboard', 'engine')
game.setNeighbor('engine', 'starboard', 'docking')
// Secret passageways
game.setNeighbor('bathroom', 'down', 'docking')
Loading…
Cancel
Save