7 Developer Reference
None of these APIs should be considered stable enough for use in projects other
than Frosthaven Manager. They should be considered stable enough for use in
Frosthaven Manager. Changes to an internally-used API should be made with care
and compelling reason.
This module implements the Area-of-Effect (AoE) language. See
Programming a Scenario and frosthaven-manager/aoe
for more information.
This module provides procedures for constructing area-of-effect diagrams.
The size of the hexes built from this module.
Returns the amount by which odd rows need shifted to align with even rows in a
hex-grid (based on hex-size
Hexes for an area-of-effect diagram: respectively, spacers, attacks, allies, and
the initiating figure.
Returns the side-length of a square rectangle which would encompass an
area-of-effect diagram of max-row
rows and max-col
a hex-grid, if the diagram were centered and superimposed on the rectangle à la
Convert an AoE spec to a shape. The spec contains a list of rows; each row
contains a line number, a flag indicating this line should be offset relative
to the lines above and below it (which are not necessarily in the spec), and a
list of column specifiers, pairing symbols with columns in sorted order.
The symbols represent the corresponding shapes, with 'g a
Convert a list of syntax objects to a spec?
In this section, subsections represented subsections of the module, indicated by
Utility procedures and contracts for verifying uniqueness. The predicate
is true if-and-only-if the input xs
duplicates. The contract unique/c
requires that a value be a
and have no duplicates. The contract unique-with/c
requires of a value v
that the result of (map key v)
7.3.1 Level Info
An instance of level-info
exposes characteristics of the level, such as
the monster level, value of gold, damage caused by traps and hazardous terrain,
and end-of-scenario experience.
A constant representing the number of possible levels, as opposed to what the
A constant representing the maximum level. The minimum level is 0.
A contract recognizing valid level numbers, used for both the scenario level and
A constant representing the maximum number of players.
A contract recognizing a valid number of players.
Returns the level-info
for the given level
Returns the amount of inspiration rewarded for completing a scenario based on
how many players participated in the scenario.
captures everything about a player that Frosthaven Manager
You will not usually need the player constructor: use the smart
constructor make-player instead.
Creates a player
In practice, player HP does not currently fall below 1. This may be a bug.
Formats the string "HP: current/max" for the player p.
A player summon. Serializable.
In practice, summon HP does not currently fall below 1. This may be a bug.
Formats the string "HP: current/max" for the summon s.
7.3.3 Loot Deck
Represents materials for loot cards.
Represents herbs for loot cards.
Represents the random-item loot card.
Represents a loot card worth 1 to 3 gold, but may have +1 stickers.
Represents a loot card for a material; the amount varies by number of players.
May have +1 stickers.
Represents a loot card worth 1 name herb, but may have +1 stickers.
This predicate recognizes valid loot cards. It is also a valid
Formats a loot card for display.
Constants designating the maximum number of certain kinds of cards.
Decks of loot cards from which you draw to make the loot deck.
Current values are the standard loot cards. Modifications via stickers are not
Monster modifier cards.
predicate recognizes all valid conditions, which are
A predicate recognizing valid initiative values.
All the conditions together.
A full deck of 20 monster modifier cards.
Full decks of 10 monster curse and bless cards.
True if-and-only-if deck
contains a null
Returns the better or worse of the two modifier cards.
7.3.5 Monster Cards
The monster statistic representation, usually used with pre-fabs.
The monster information representation, often for reading pre-fab structs.
The monster ability representation, often for reading pre-fab structs.
Note that pre-fab syntax does not permit path? objects.
A contract that recognizes valid monster numbers.
captures the individual status of a monster, but not its
game statistics. Those are listed in its parent monster-group
Prefer the smart constructor make-monster.
Prefer the smart constructor make-monster-group and the update
functions, which maintain an invariant of monsters sorted by eliteness and
Calculates the maximum HP value of stats, which may be a formula.
Calculates the attack value of stats, which may be a formula.
Returns a string suitable for display to indicate the name of a possibly-absent
Returns a string suitable for display to indicate the initiative of a
possibly-absent monster ability.
Formats a single ability on a monster ability card, as from
, by replacing keywords like “Attack +1”
with calculated text and values.
Returns a list of “extras” for rendering a specific ability-text
. The meaning of each extra spec is as follows:
Populates the resulting monster
based on the statistics from
. Formulas are calculated using env
Creates a monter-group at level level based on the statistics
The num+elite?s parameter provides a mapping from (unique) monster
numbers to their elite status. Only monster numbers in the mapping are added to
Formulas are calculated using env.
Transforms (monster-conditions m)
by adding the condition
or removing it otherwise.
The number of the first monster in the monster group mg, or
#false if there are no such monsters.
Formats the string "HP: current/max" for the monster m.
The same monster group, but with all elite monsters normal and vice-versa.
The same monster, but normal instead of elite and vice-versa.
The size of the element pictures.
A container for a named set of element pictures.
Returns all of the elements bundled together. This module also provides bindings
from the names of the elemnts to procedures returning element-pics
values, but they are not documented here. See Elements Tracker
various element names and pictures.
(define-serializable-enum-type id (constant-id ...) enum-option ...)
|enum-option|| ||=|| ||#:omit-root-binding|
| || ||||| ||#:descriptor-name descriptor-id|
| || ||||| ||#:predicate-name predicate-id|
| || ||||| ||#:discriminator-name discriminator-id|
| || ||||| ||#:selector-name selector-id|
| || ||||| ||#:property-maker prop-maker-expr|
| || ||||| ||#:inspector inspector-expr|
This module reprovides all the bindings from
This module provides facilities for manipulating manager-level state.
A creature is identified by its unique creature-id.
All of the "global" manager state.
Create an initial state.
Derives a formula environment observable from pieces of s.
Procedures to serialize and deserialize a state?
Copies the state from from
by updating the internal
observables. This makes it possible to update an existing state?
the values from a deserialized state?
Undo procedures. To create an observable undo state that tracks s
. Then, when undoable?
is true of the observable
undo state, use (undo! s @undo)
to actually trigger change.
Warning: sometimes multiple undos are necessary to be coherent. Not all state
changes are recorded.
Updates player or monster-group k
When updating a monster-group, fn
can update the
Updates all players or monster-groups in creatures via f.
Updates player ks name to name or max health via f.
Calculates a creature’s initiative.
Adds or removes a monster group based on the received event.
It is the caller’s responsibility to verify that a monster has been added and
needs to potentially trigger a new card.
True if, according to in-draw?, initiative values should be publicly
Monster ability deck, with currently active card, draw pile, and discard pile.
Draws a card from the ability deck.
Discards the active card and shuffles the ability deck if necessary.
Updates each deck via f.
Moves the top card of the draw pile to its bottom.
This module provides facilities for manipulating the modifier deck.
Reshuffle the monster modifier deck.
Discard a card to the appropriate pile.
Draws and discards a single modifier card.
Draws two modifier cards and discards them with the kept card on top.
Add a curse or bless to the appropriate deck.
This module provides facilities for manipulating the active monster databases.
Initialize the active monster databases.
This module provides facilities for manipulating the loot deck.
Converts a count of cards per deck into an shuffled deck of loot cards. This can
be considered the interpreter for a language whose values are like those
produced by loot-picker
mappings from decks to number of cards.
Give player k the top loot card.
Rotate the top loot card to the bottom of the deck.
The following sections describe modules under frosthaven-manager/gui.
Menu items for Frosthaven Manager.
A GUI component for a counter with a label and up and down callbacks.
A contract recognizing valid element states.
Returns a GUI view displaying the element-pics
. Each element of
is controlled by the corresponding element of @states
Builds an equally-sized list of element states to control es
Set all element states es to 'infused or 'unfused,
Returns the new element state after waning for one cycle.
Returns the new element state after cycling once, with unfused wrapping around
This module provides helpers for manipulating font objects, as in
|(copy-font|| ||f|| |
| || [||#:size size|| |
| || ||#:face face|| |
| || ||#:family family|| |
| || ||#:style style|| |
| || ||#:weight weight|| |
| || ||#:underlined? underlined?|| |
| || ||#:smoothing smoothing|| |
| || ||#:size-in-pixels? size-in-pixels?|| |
| || ||#:hinting hinting|| |
| || ||#:feature-settings feature-settings|| |
| || ||#:font-list font-list])|| |
| → (is-a?/c font%)|
| f : (is-a?/c font%)|
| ||size|| ||:|| ||(real-in 0.0 1024.0)|
| || || ||=|| ||(send f get-size size-in-pixels?)|
| face : (or/c string? #f) = (send f get-face)|
| ||family|| ||:|| ||(or/c 'default 'decorative 'roman 'script 'swiss 'modern 'symbol 'system)|
| || || ||=|| ||(send f get-family)|
| style : (or/c 'normal 'italic 'slant) = (send f get-style)|
| weight : font-weight/c = (send f get-weight)|
| underlined? : any/c = (send f get-underlined)|
| ||smoothing|| ||:|| ||(or/c 'default 'partly-smoothed 'smoothed 'unsmoothed)|
| || || ||=|| ||(send f get-smoothing)|
| size-in-pixels? : any/c = (send f get-size-in-pixels)|
| hinting : (or/c 'aligned 'unaligned) = (send f get-hinting)|
Copy all the features of font f to a brand new font object. Supply
modified values via the keyword arguments.
This module provides GUI objects for interactive formula editing.
A window containing an interactive formula editor.
A menu item that displays an interactive formula editor.
Returns translated x and y coordinates relative to
top, assuming they were originally relative to this.
A GUI view that displays the level-info
A GUI view of a button that shows a table of level-info
values for each
level. The current @level
A GUI view of a button that shows a table of inspiration rewards for each
possible number of players. The current @num-players starts selected.
A GUI view to build a loot deck by including certain loot cards. The callback
on-card is invoked with an "event" that specifies a deck of cards from
which one card should be added or removed. Similarly for on-sticker to
add stickers to decks.
A GUI view of a button that, when clicked, shows a view to assign the top loot
card from @loot-deck
to one of @players
via buttons. The
is invoked with the ID (cdr
) of the player
whose button is clicked to assign loot; it can be used
, assign the loot card. After on-player
the view is closed.
Additionally, buttons for the top and bottom of the deck trigger the
on-top and on-bottom callbacks, which then also close the
See Scenario Information and Loot for how loot-button
functions in Frosthaven Manager.
A button that, when clicked, shows a loot deck previewer.
This module’s main function is to run the Frosthaven Manager. It provides only
a single binding:
A GUI view rendering the markdown in @content
, which is either a
of Markdown or a path to a file containing Markdown.
The view updates when @content
note that in the string case
this means the Markdown content has changed, but in the path case this means the
path has changed, not the contents of the file at the path!
The following Markdown features are supported:
Unordered and ordered lists;
Bold, italic, and code styles;
and six levels of headings.
The following xexpr?
s are supported recursively in the parsed Markdown;
these map to the Markdown features above:
Any expression tagged !HTML-COMMENT, the tag for HTML comments
Any expression tagged a
Any expression tagged blockquote
Any expression tagged ul
Any expression tagged ol
Any expression tagged li
Any expression tagged hr
Any expression tagged p
Any expression tagged strong
Any expression tagged em
Any expression tagged code
Any expression tagged h1
Any expression tagged h2
Any expression tagged h3
Any expression tagged h4
Any expression tagged h5
Any expression tagged h6
Any other tag found in the parsed Markdown is a runtime error.
Note that Markdown technically requires 4 spaces or a single tab as leading
indent for nesting lists and other blocks; while many Markdown implementations
(such as those used on GitHub) are more lenient, the implementation backing
markdown-text is stricter on this point.
Produces a mixin
that calls out
with a procedure that closes the window. Many uses of out
are to store
a local binding to this "close" procedure.
If the mixin set-close-mixin-id
is applied to a
is a nullary procedure that
Contracts for events used in callbacks to monster GUI views. Best used with
A GUI view used to build a monster group by choosing the set, name, and included
monsters (along with their elite status and level). The available choices come
from info-db less unavailable (a set of monster names). The
callback on-change is invoked each time changes are made. The default
monster level is specified by @initial-level.
A GUI view of a monster group showing a table of monsters and some other
information about the group.
A GUI view used to choose the monsters in a scenario: it composes
in order to allow selection and removal of entire
groups. The callback on-change
is invoked to notify of the addition or
removal of a group. Other parameters are used as in
A GUI view used to display an entire monster group. See
Monster Group Controls
. An ability is displayed if an ability card is
present in @ability-deck
. The @monster-num
currently selected monster in the detailed portion of the view.
The callbacks function as follows:
on-select is given a new monster number when one is selected in the detailed view, or #false if there are none.
on-condition is given a monster number, condition, and either #true or #false to indiciate whether the condition should be applied or removed.
on-hp is given a monster number and a procedure to update the monsters monster-current-hp.
on-kill is invoked with a monster number when that monster is killed.
on-new is invoked with a monster number and #true if the monster is elite or #false otherwise for a newly added monster.
on-swap is invoked with 'all if all monsters should be swapped by swap-monster-group-elites, or with a monster number if only that monster should be swapped by swap-monster-elite.
on-move-ability-card is invoked when the top of the ability draw pile should be moved to the bottom using the ability deck previewer.
Any pre-set monster groups will also be shown.
Renders a dialog to add a monster group by invoking the callback
on-group if one is selected. The value of @initial-level is
used for the initial level of the group, which can be adjusted in the dialog.
Similarly, @monster-names specifies which names are not available for
the new group.
Originally an internal part of the implementation of
multi-monster-picker until it had uses in the main playing view.
A GUI view to enter player names and max HP. The number of entry slots is
determined by @num-players
. The callbacks on-name
are invoked with a player number and a name or a procedure to
. Default names and max HP values can be specified
A GUI view of a single player. See Player Controls
. The callback
is given an condition and value that determines whether
the condition should be applied (#true
) or removed (#false
The callbacks on-hp
are given procedures to modify
, respectively. The callback
is given a new initiative for player-initiative
The number of players is used to format the player’s loot appropriately.
The summon callbacks are given the summon number, a list index, to indicate
which summon to update. Adding a summon is done by name and max HP.
A parameter for the current renderer. This can be set so that sub-views can
access the top-level renderer. Note that it is not re-entrant, in the sense that
to make it effective one must render an application by
Any other application running in the same thread cannot use
or it will interfere with the previous application.
This also holds more generally of sub-views render
ed on-the-fly. See
to avoid this.
This will not affect multiple applications built and run separately that use
this library, since they’re in separate processes completely.
Renders (as in render
with parent parent
, then queues a high-priority callback in the
handler-thread for es
to set current-renderer
to the resulting
renderer, which is returned.
Pass a new eventspace created with
make-eventspace to separate the rendered tree and
corresponding current-renderer from other applications.
This can be used to group windows in an application together, but note that
subsequent calls with the same es will override that eventspace’s
handler thread’s current-renderer.
For a short-lived window that should tear down the eventspace on closure,
combine with with-closing-custodian/eventspace.
Evaluates the body expressions e ...
with the following special
For example, the following produces either #t
on whether window A or window B was closed first. Note also the use of
to set current-renderer
This module contains views for end-of-scenario rewards.
Produces a window
for displaying a players rewards, such as loot, gold,
and XP. The selected player’s loot cards are also displayed. The mixin
is applied to the window
A view of @data
using stacked tables. The tables are horizontal,
left-to-right by default. Supplying vpanel
stack vertical. When topleft?
is true, the first table is on the left
or top of the stack. Otherwise it is on the right or bottom, reversing the order
of subsequent tables.
The stack of tables is determined by column1 and each
column-spec. The first is always column1.
Starting with @data and column1, a table is added to the
stack. The table’s title is given by column-title. The labels for the
items in the table come from applying column-entry->label to the values
in the data. When a value is selected, the data for the next table and
column-spec is produced by column-entry->next on the
selection. This value is automatically wrapped in vector as needed.
This process continues, adding tables to the stack whose data depends on
previous data and selections, until the final table and column-spec are
added. The final selection, which is not automatically vectorized, is
given to final-view. The resulting view is also added to the stack.
The intermediate data produced by column-entry->next
emptied when no value is selected previously. In contrast, final-view
needs to handle the case that no data has yet been selected. A common pattern
is to compute a default value:
A column specification for stacked-tables
, which explains how the
specification is used.
A note about column-entry->next: you almost certainly want to return a
vector for all but (possibly) the last column. Intermediate
columns likely have multiple choices. As a convenience, when there is
only one, you may omit the vector. For the final column, you likely
want to omit the vector unless the selected data is one: the data here is the
final selection, of which there should probably be one.
A GUI view for the start screen of Frosthaven Manager. The callbacks are invoked
with the level and number of players for each update to those values.
A GUI view for static tables. The columns are labelled by columns
there are exactly num-rows
rows. Each row is indexed by a natural
to (sub1 num-rows)
(entry->value (index->entry i))
computes a value v
the functions in entry->columns
are called to compute the values of the
columns for that row. Each row is labelled with the entry (index->entry i)
Summarizing: each row is indexed by a natural number in the range
[0,num-rows). An entry is computed by index->entry. A value is
computed from the entry by entry->value. From this value, functions in
entry->columns compute the elements of the row.
The selection is determined by @selection as with table.
The column widths are calculated automatically based on columns, or are
provided as widths.
This module implements the bestiary language. See
Programming a Scenario and
frosthaven-manager/bestiary for more information.
See Programming a Scenario for more information on custom monster
Reads db-file and produces the monster databases.
The demo, default monster database included with Frosthaven Manager.
This module contains parsers for #lang
Programming a Scenario for more details.
The result is syntax?
with source src
true, and the datum it contains matches foes/pc
Contracts for foes values.
Textual parsers for parts of the foes language.
This module contains parsers for arithmetic formulas over addition, subtraction,
multiplication, division, rounding, and a limited set of variables. The parse
result is a function from an environment of variables to a number.
Contracts for the parse results of formulas.
Textual parser for formulas.
Parses a string as a formula or fails.
This module contains parsers for #lang
Programming a Scenario for more details.
The result is syntax?
with source src
true, and the datum it contains matches bestiary/c
A contract for bestiary values.
Textual parsers for parts of the bestiary language.
Returns duplicate monster names from bestiaries and ability decks in
. The first value is based on any monster-info
s and the
second on monster-ability
In addition to the shorthands below, this module exports define/obs,
@, :=, and λ:= from
This collection holds pretty printers based on
This module pretty-prints bestiary files. It can be run as a program with
racket -l- frosthaven-manager/pp/bestiary
to format standard in or a provided file to standard out. Use --help for
Creates a document for pretty printing from the results of a parsed bestiary.
The document starts with a #lang
line preceding the result if
is not #f
This modules provides everything from qi in addition to the
bindings from frosthaven-manager/qi/list2hash.
(list~>hash maybe->key maybe->value)
|maybe->key|| ||=|| |
| || ||||| ||#:->key ->key-flo|
| || || || || |
|maybe->value|| ||=|| |
| || ||||| ||#:->value ->value-flo|
This Qi form transforms the input value (a list) into a hash, where each element
of the list is mapped into a key via ->key-flo
and a value via
. It uses list->hash
Transforms xs to a hash by mapping each element into a key via
->key and a value via ->value.
Launches the actual web server for s. The callback protocol for
send-event is not yet formalized and very unstable.
Returns the server address (on a best-guess basis) and a stop procedure
that stops the server when called.
The modules in this collection provide helpers for macros, syntax, and
This expander language wraps syntax/module-reader by assuming a
specific reading protocol.
This module does not have a reader of its own, so should be used with
module or #lang s-exp.
The following example demonstrates the entire grammer of the expander language:
|#lang s-exp frosthaven-manager/syntax/module-reader|
|[parse-foes from frosthaven-manager/parsers/foes]|
|(module reader frosthaven-manager/syntax/module-reader|
| [parse-foes from frosthaven-manager/parsers/foes])|
The semantics are as follows. The resulting module satisfies the language reader
extension protocol from Reading via an Extension
via syntax/module-reader with a few specifications. The
expander-mod-path is used as in syntax/module-reader to
determine the module-path for the initial bindings of modules produced by the
reader. The parser-id, which must be provided by
parser-mod-path, is assumed to parse the whole body as with the
#:whole-body-readers? keyword for syntax/module-reader.
In addition, it should support the following protocol: the parser accepts 2
positional arguments. The first is the same name-value as