Skip to content

Commit

Permalink
Scenario descriptions in tooltips (#251)
Browse files Browse the repository at this point in the history
* add descriptions to maps
* amend scenario making docs
  • Loading branch information
mlange-42 authored Mar 17, 2024
1 parent 06e5dfc commit cfe4303
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 16 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
### Documentation

* Adds doc-strings for all resources (#159)
* Adds documentation on scenario editing and creation under [`docs/SCENARIOS.md`](https://github.com/mlange-42/tiny-world/blob/main/docs/SCENARIOS.md) (#224)
* Adds documentation on scenario editing and creation under [`docs/SCENARIOS.md`](https://github.com/mlange-42/tiny-world/blob/main/docs/SCENARIOS.md) (#224, #251)

### Other

Expand Down
3 changes: 3 additions & 0 deletions data/maps/Coastline.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
6^ 20~ 1+ 14t 2r 50-
500
landscape-architect fisherman-guild
A medium-sized (40x40) map with a coastline and a river. Plenty of all resources.
Available random tiles: 500.
----
18 20
.................~.....~................
---------------tt~-^^^-~----------------
Expand Down
3 changes: 3 additions & 0 deletions data/maps/Desert Valley.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
15- 1^ 4~ 40+ 4t 3r
500
landscape-architect
A medium-sized (40x40) map with a green valley through a vast desert. Very limited on building space.
Available random tiles: 500.
----
22 19
....................++++++++++++.........
................+++++++UU+++++++++.......
Expand Down
3 changes: 3 additions & 0 deletions data/maps/Great Plains.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
2~ 3^ 3r 20t 250-
250
landscape-architect farmer-guild
A medium-sized (43x43) map with vast plains and a few hills and forest patches. Resources are rare.
Available random tiles: 250.
----
21 21
-------------------------------------------
----------------------------------tt-------
Expand Down
3 changes: 3 additions & 0 deletions data/maps/River Delta.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
4^ 10~ 0+ 12t 1r 50-
0
landscape-architect wood-gnome fisherman-guild farmer-guild
A larger (53x46) map of a river delta. Plenty of resources, but a lot of waterways to bridge.
Available random tiles: 0!
----
24 25
........................~~...........................
------------------------~~---------------------------
Expand Down
3 changes: 3 additions & 0 deletions data/maps/River.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
1r 20- 4^ 6~ 1+ 6t
500
play-the-game
A small (20x20) starting area with a river.
Available random tiles: 500.
----
8 8
......---------~....
....-----------~-...
Expand Down
3 changes: 3 additions & 0 deletions data/maps/Rolling Hills.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
50- 20^ 6~ 20t 0+ 1r
500
landscape-architect shepherd-guild
A small-ish (25x25) map with lots of hills and trees, and a river.
Available random tiles: 500.
----
12 12
TTTTT---TTTT-------ttt-TTT
TTTt-----TT-------tTTT--TT
Expand Down
3 changes: 3 additions & 0 deletions data/maps/Swamp Forest.asc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
25t 1r 40- 1^ 6~
500
wood-gnome
A small-ish (27x27) map with a swampy forest full of ponds.
Available random tiles: 500.
----
13 13
............---............
........-----t-----........
Expand Down
9 changes: 7 additions & 2 deletions docs/SCENARIOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Further, terrain is not only placed by clicking, but also by dragging the mouse.
Saving a game in editor mode is like saving the editor session. Saving the map means to export it in the [Map Format](#map-format) for use as a scenario.

In a final step, random terrain frequencies for the scenario,
as well as required achievement, can be tweaked by editing the exported scenario.
as well as required achievement and the map description can be tweaked by editing the exported scenario.

## Map Format

Expand All @@ -30,7 +30,8 @@ A small example map is shown below.
* The 1st line contains frequencies of random terrains.
* The second line contains the number of initially placable trains.
* The 3rd line contains a list of required achievements, separated by spaces.
* The 4th line contains the relative coordinates of the starting position, from the top-left corner (0,0).
* Subsequent lines contain the map description, up to the first line that starts with `----`.
* The 1st line after the delimiter `----` contains the relative coordinates of the starting position, from the top-left corner (0,0).
* All further lines are the actual map.

Terrain characters are defined in [`data/json/terrain.json`](https://github.com/mlange-42/tiny-world/blob/main/data/json/terrain.json).
Expand All @@ -40,6 +41,10 @@ Achievements are defined in [`data/json/achievements.json`](https://github.com/m
1r 20- 6^ 6~ 1+ 6t
500
play-the-game
Description of the map.
Can be an arbitrary number of lines.
Terminated by a line starting with ----
----
8 8
......---------~....
....-----------~-...
Expand Down
1 change: 1 addition & 0 deletions game/maps/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type Map struct {
Terrains []rune
Data [][]rune
Achievements []string
Description string
Center image.Point
InitialRandomTerrains int
}
18 changes: 11 additions & 7 deletions game/menu/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,18 +573,18 @@ func (ui *UI) createScenariosPanel(games []save.SaveGame, achievements *achievem

mapsUnlocked := []save.MapLocation{}
mapsLocked := []save.MapLocation{}
achUnlocked := [][]string{}
achLocked := [][]string{}
achUnlocked := []save.MapInfo{}
achLocked := []save.MapInfo{}
cntEnabled := 0

for _, m := range maps {
ach, err := save.LoadMapAchievements(ui.fs, ui.mapsFolder, m)
ach, err := save.LoadMapData(ui.fs, ui.mapsFolder, m)
if err != nil {
log.Fatalf("error loading achievements for map %s: %s", m.Name, err.Error())
}

enabled := true
for _, a := range ach {
for _, a := range ach.Achievements {
a2, ok := achievements.IdMap[a]
if !ok {
log.Printf("WARNING: Achievement '%s' in map '%s' not found", a, m.Name)
Expand Down Expand Up @@ -622,8 +622,8 @@ func (ui *UI) createScenariosPanel(games []save.SaveGame, achievements *achievem
)

achieve := ""
if len(ach) > 0 {
for _, a := range ach {
if len(ach.Achievements) > 0 {
for _, a := range ach.Achievements {
if name, ok := achievements.IdMap[a]; ok {
if name.Completed {
achieve += fmt.Sprintf("\n - %s", name.Name)
Expand All @@ -641,10 +641,14 @@ func (ui *UI) createScenariosPanel(games []save.SaveGame, achievements *achievem
localText = " (*local)"
localMarker = " (*)"
}
description := ""
if len(ach.Description) > 0 {
description = ach.Description + "\n\n"
}

label := widget.NewText(
widget.TextOpts.ProcessBBCode(true),
widget.TextOpts.Text(fmt.Sprintf("%s%s\n\nRequired achievements:\n%s", m.Name, localText, achieve), fonts.Default, ui.sprites.TextColor),
widget.TextOpts.Text(fmt.Sprintf("%s%s\n\n%sRequired achievements:\n%s", m.Name, localText, description, achieve), fonts.Default, ui.sprites.TextColor),
widget.TextOpts.Position(widget.TextPositionStart, widget.TextPositionCenter),
widget.TextOpts.MaxWidth(360),
)
Expand Down
40 changes: 34 additions & 6 deletions game/save/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ type saveTime struct {
Time time.Time
}

type MapInfo struct {
Achievements []string
Description string
}

const (
LoadTypeNone LoadType = iota
LoadTypeGame
Expand Down Expand Up @@ -119,7 +124,18 @@ func ParseMap(mapStr string) (maps.Map, error) {
}
}

sizeLine := lines[3]
description := []string{}
lineIdx := 3
for {
line := lines[lineIdx]
lineIdx++
if strings.HasPrefix(line, mapDescriptionDelimiter) {
break
}
description = append(description, line)
}

sizeLine := lines[lineIdx]
parts := strings.Split(sizeLine, " ")
cx, err := strconv.Atoi(parts[0])
if err != nil {
Expand All @@ -130,7 +146,7 @@ func ParseMap(mapStr string) (maps.Map, error) {
panic(fmt.Sprintf("can't convert to integer: `%s`", parts[1]))
}

lines = lines[4:]
lines = lines[lineIdx+1:]

for _, s := range lines {
if len(s) > 0 {
Expand All @@ -145,16 +161,17 @@ func ParseMap(mapStr string) (maps.Map, error) {
InitialRandomTerrains: randTerr,
Center: image.Pt(cx, cy),
Achievements: achievements,
Description: strings.Join(description, "\n"),
}, nil
}

func LoadMapAchievements(f fs.FS, folder string, mapLoc MapLocation) ([]string, error) {
func LoadMapData(f fs.FS, folder string, mapLoc MapLocation) (MapInfo, error) {
mapStr, err := loadMap(f, folder, mapLoc)
if err != nil {
return nil, err
return MapInfo{}, err
}

lines := strings.SplitN(strings.ReplaceAll(mapStr, "\r\n", "\n"), "\n", 4)
lines := strings.Split(strings.ReplaceAll(mapStr, "\r\n", "\n"), "\n")

ach := strings.Split(lines[2], " ")
achievements := []string{}
Expand All @@ -164,7 +181,18 @@ func LoadMapAchievements(f fs.FS, folder string, mapLoc MapLocation) ([]string,
}
}

return achievements, nil
description := []string{}
lineIdx := 3
for {
line := lines[lineIdx]
lineIdx++
if strings.HasPrefix(line, mapDescriptionDelimiter) {
break
}
description = append(description, line)
}

return MapInfo{Achievements: achievements, Description: strings.Join(description, "\n")}, nil
}

func ListMaps(f fs.FS, folder string) ([]MapLocation, error) {
Expand Down
5 changes: 5 additions & 0 deletions game/save/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/mlange-42/tiny-world/game/terr"
)

const mapDescriptionDelimiter = "----"

func SaveWorld(folder, name string, world *ecs.World, skip []generic.Comp) error {
js, err := as.Serialize(world,
as.Opts.SkipResources(
Expand Down Expand Up @@ -82,6 +84,9 @@ func SaveMap(folder, name string, world *ecs.World) error {
// Space for required achievements
b.WriteString("\n")

// Delimiter for map description
b.WriteString(mapDescriptionDelimiter + "\n")

cx, cy := terrain.Width()/2, terrain.Height()/2
b.WriteString(fmt.Sprintf("%d %d\n", cx-bounds.Min.X, cy-bounds.Min.Y))

Expand Down

0 comments on commit cfe4303

Please sign in to comment.