| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 | 
							- package main
 
- import (
 
- 	"fmt"
 
- 	"math/rand"
 
- 	"os"
 
- 	"path/filepath"
 
- 	"red-green/door"
 
- 	"regexp"
 
- 	"strconv"
 
- 	"strings"
 
- 	"time"
 
- 	"unicode"
 
- 	_ "github.com/mattn/go-sqlite3"
 
- 	"github.com/seehuhn/mt19937"
 
- )
 
- var Config map[string]string
 
- func find_words(text string) [][]int {
 
- 	word, _ := regexp.Compile("([A-Za-z]+)")
 
- 	return word.FindAllStringIndex(text, -1)
 
- }
 
- func press_a_key(d *door.Door) int {
 
- 	green := door.ColorText("BOLD GREEN")
 
- 	blue := door.ColorText("BOLD BLUE")
 
- 	yellow := door.ColorText("BOLD YELLOW")
 
- 	any_caps := green
 
- 	any_lower := yellow
 
- 	any_color := func(text string) string {
 
- 		var output string
 
- 		var lastColor string
 
- 		for _, letter := range text {
 
- 			if unicode.IsUpper(letter) {
 
- 				if lastColor != any_caps {
 
- 					lastColor = any_caps
 
- 					output += any_caps
 
- 				}
 
- 				output += string(letter)
 
- 			} else {
 
- 				if lastColor != any_lower {
 
- 					lastColor = any_lower
 
- 					output += any_lower
 
- 				}
 
- 				output += string(letter)
 
- 			}
 
- 		}
 
- 		return output
 
- 	}
 
- 	text := "Press a key to continue..."
 
- 	work_text := []rune(text)
 
- 	d.Write(door.Reset + any_color(text))
 
- 	var r int = -1
 
- 	var t int
 
- 	sleep_ms := 250
 
- 	ms_sleep := 0
 
- 	words := find_words(text)
 
- 	var word int = 0
 
- 	var wpos int = 0
 
- 	current_word := text[words[word][0]:words[word][1]]
 
- 	t = 0
 
- 	r = d.WaitKey(0, int64(sleep_ms)*1000)
 
- 	for r == -1 {
 
- 		ms_sleep += sleep_ms
 
- 		if ms_sleep > 1000 {
 
- 			ms_sleep -= 1000
 
- 			t++
 
- 			if t >= int(door.Inactivity) {
 
- 				d.Write(strings.Repeat("\b", len(text)))
 
- 				d.Write(any_color(text) + door.CRNL)
 
- 				return -1
 
- 			}
 
- 		}
 
- 		wpos++
 
- 		if wpos == len(current_word) {
 
- 			word++
 
- 			wpos = 0
 
- 			work_text = []rune(text)
 
- 			if word == len(words) {
 
- 				word = 0
 
- 				if any_caps == green {
 
- 					any_caps = blue
 
- 				} else {
 
- 					any_caps = green
 
- 				}
 
- 				d.Write(strings.Repeat("\b", len(text)))
 
- 				d.Write(any_color(string(work_text)))
 
- 				current_word = text[words[word][0]:words[word][1]]
 
- 				goto READKEY
 
- 			}
 
- 			current_word = text[words[word][0]:words[word][1]]
 
- 		}
 
- 		{
 
- 			c := rune(current_word[wpos])
 
- 			for !unicode.IsLower(c) {
 
- 				wpos++
 
- 				if wpos == len(current_word) {
 
- 					wpos = 0
 
- 					word++
 
- 					work_text = []rune(text)
 
- 					if word == len(words) {
 
- 						word = 0
 
- 					}
 
- 					current_word = text[words[word][0]:words[word][1]]
 
- 				}
 
- 				c = rune(current_word[wpos])
 
- 			}
 
- 			// Ok, we found something that's lower case
 
- 			work_text[words[word][0]+wpos] = unicode.ToUpper(c)
 
- 		}
 
- 		d.Write(strings.Repeat("\b", len(text)))
 
- 		d.Write(any_color(string(work_text)))
 
- 	READKEY:
 
- 		r = d.WaitKey(0, int64(sleep_ms)*1000)
 
- 	}
 
- 	d.Write(strings.Repeat("\b", len(text)))
 
- 	d.Write(any_color(text))
 
- 	return r
 
- }
 
- func MainMenu() door.Menu {
 
- 	// Make the main menu
 
- 	m := door.Menu{Panel: door.Panel{Width: 25,
 
- 		X:           5,
 
- 		Y:           5,
 
- 		Style:       door.DOUBLE,
 
- 		Title:       "[ Main Menu: ]",
 
- 		TitleOffset: 3,
 
- 		BorderColor: door.ColorText("BRI CYAN ON BLA")}}
 
- 	m.SelectedR = door.MakeMenuRender(door.ColorText("BOLD CYAN"),
 
- 		door.ColorText("BOLD BLUE"),
 
- 		door.ColorText("BOLD CYAN"),
 
- 		door.ColorText("BOLD BLUE"))
 
- 	m.UnselectedR = door.MakeMenuRender(door.ColorText("BOLD YEL ON BLUE"),
 
- 		door.ColorText("BOLD WHI ON BLUE"),
 
- 		door.ColorText("BOLD YEL ON BLUE"),
 
- 		door.ColorText("BOLD CYAN ON BLUE"))
 
- 	m.AddSelection("P", "Play Cards")
 
- 	m.AddSelection("S", "View Scores")
 
- 	m.AddSelection("C", "Configure")
 
- 	m.AddSelection("H", "Help")
 
- 	m.AddSelection("A", "About this game")
 
- 	m.AddSelection("Q", "Quit")
 
- 	return m
 
- }
 
- func ConfigMenu() door.Menu {
 
- 	m := door.Menu{Panel: door.Panel{Width: 31,
 
- 		X:           5,
 
- 		Y:           5,
 
- 		Style:       door.DOUBLE,
 
- 		Title:       "[ Configuration Menu ]",
 
- 		TitleColor:  door.ColorText("BRI CYAN ON BLUE"),
 
- 		BorderColor: door.ColorText("CYAN ON BLUE")}}
 
- 	m.SelectedR = door.MakeMenuRender(door.ColorText("BOLD CYAN"),
 
- 		door.ColorText("BOLD BLUE"),
 
- 		door.ColorText("BOLD CYAN"),
 
- 		door.ColorText("BOLD BLUE"))
 
- 	m.UnselectedR = door.MakeMenuRender(door.ColorText("BOLD YEL ON BLUE"),
 
- 		door.ColorText("BOLD WHI ON BLUE"),
 
- 		door.ColorText("BOLD YEL ON BLUE"),
 
- 		door.ColorText("BOLD CYAN ON BLUE"))
 
- 	m.AddSelection("D", "Deck Colors")
 
- 	m.AddSelection("V", "View Settings")
 
- 	m.AddSelection("Q", "Quit")
 
- 	return m
 
- }
 
- func display_information(d *door.Door) {
 
- 	d.Write(door.Clrscr)
 
- 	keyColor := door.ColorText("BRI GREEN")
 
- 	sepColor := door.ColorText("BRI YEL")
 
- 	valColor := door.ColorText("CYAN")
 
- 	nice_format := func(key string, value string) string {
 
- 		return fmt.Sprintf("%s%-20s %s: %s%s", keyColor, key, sepColor, valColor, value) + door.CRNL
 
- 	}
 
- 	d.Write(nice_format("BBS Software", d.Config.BBSID))
 
- 	d.Write(nice_format("Real Name", d.Config.Real_name))
 
- 	d.Write(nice_format("Handle", d.Config.Handle))
 
- 	d.Write(nice_format("User #", strconv.Itoa(d.Config.User_number)))
 
- 	d.Write(nice_format("Security Level", strconv.Itoa(d.Config.Security_level)))
 
- 	d.Write(nice_format("Node #", strconv.Itoa(d.Config.Node)))
 
- 	d.Write(nice_format("Unicode", strconv.FormatBool(door.Unicode)))
 
- 	d.Write(nice_format("CP437", strconv.FormatBool(door.CP437)))
 
- 	d.Write(nice_format("Screen Size", fmt.Sprintf("%d X %d", door.Width, door.Height)))
 
- }
 
- func panel_demo(d *door.Door) {
 
- 	width := 55
 
- 	fmtStr := "%-55s"
 
- 	p := door.Panel{X: 5, Y: 5, Width: width, Style: door.DOUBLE, BorderColor: door.ColorText("CYAN ON BLUE"), Title: "[ Panel Demo ]"}
 
- 	lineColor := door.ColorText("BRIGHT WHI ON BLUE")
 
- 	// Add lines to the panel
 
- 	for _, line := range []string{"The BBS Door Panel Demo", "(C) 2021 Red Green Software, https://red-green.com"} {
 
- 		if door.Unicode {
 
- 			line = strings.Replace(line, "(C)", "\u00a9", -1)
 
- 		}
 
- 		l := door.Line{Text: fmt.Sprintf(fmtStr, line), DefaultColor: lineColor}
 
- 		p.Lines = append(p.Lines, l)
 
- 	}
 
- 	p.Lines = append(p.Lines, p.Spacer())
 
- 	p.Lines = append(p.Lines, door.Line{Text: fmt.Sprintf(fmtStr, "Welcome to golang!"), DefaultColor: lineColor})
 
- 	d.Write(door.Clrscr)
 
- 	d.Write(p.Output() + door.CRNL)
 
- }
 
- func MakeColorsRender(brackets string, text_color string, colors map[string]string) func(string) string {
 
- 	renderF := func(text string) string {
 
- 		words := find_words(text)
 
- 		var option bool = true
 
- 		var color_word bool = false
 
- 		var result string
 
- 		var last_color string
 
- 		var word_color string
 
- 		var words_id = 0
 
- 		word_pair := words[words_id]
 
- 		normal := colors["ALL"]
 
- 		for tpos, c := range text {
 
- 			if option {
 
- 				if c == '[' || c == ']' {
 
- 					if last_color != brackets {
 
- 						result += brackets
 
- 						last_color = brackets
 
- 					}
 
- 					if c == ']' {
 
- 						option = false
 
- 					}
 
- 				} else {
 
- 					if last_color != text_color {
 
- 						result += text_color
 
- 						last_color = text_color
 
- 					}
 
- 				}
 
- 				result += string(c)
 
- 			} else {
 
- 				// Out of the options
 
- 				if color_word {
 
- 					if tpos < word_pair[1] {
 
- 						if last_color != word_color {
 
- 							result += word_color
 
- 							last_color = word_color
 
- 						} else {
 
- 							color_word = false
 
- 							if last_color != normal {
 
- 								result += normal
 
- 								last_color = normal
 
- 							}
 
- 						}
 
- 						result += string(c)
 
- 					}
 
- 				} else {
 
- 					// look for COLOR word
 
- 					if tpos >= word_pair[1] {
 
- 						words_id++
 
- 						if words_id >= len(words) {
 
- 							word_pair = []int{999, 999}
 
- 						} else {
 
- 							word_pair = words[words_id]
 
- 						}
 
- 					}
 
- 					if word_pair[0] == tpos {
 
- 						// start of word
 
- 						possible := text[word_pair[0]:word_pair[1]]
 
- 						color_code, has := colors[strings.ToUpper(possible)]
 
- 						// log.Printf("Match %s / found %s %#v\n", possible, color_code, has)
 
- 						if has {
 
- 							word_color = color_code
 
- 						} else {
 
- 							word_color = colors["ALL"]
 
- 						}
 
- 						if last_color != word_color {
 
- 							result += word_color
 
- 							last_color = word_color
 
- 						}
 
- 					}
 
- 					result += string(c)
 
- 				}
 
- 			}
 
- 		}
 
- 		return result
 
- 	}
 
- 	return renderF
 
- }
 
- var DeckColors []string
 
- func init() {
 
- 	DeckColors = []string{
 
- 		"All", "Brown", "Green", "Red", "Blue", "Cyan", "Magenta", "White"}
 
- }
 
- func DeckColorMenu() door.Menu {
 
- 	m := door.Menu{Panel: door.Panel{Width: 31,
 
- 		X:           5,
 
- 		Y:           5,
 
- 		Style:       door.DOUBLE,
 
- 		Title:       "[ Deck Menu ]",
 
- 		TitleColor:  door.ColorText("BRI CYAN ON BLUE"),
 
- 		BorderColor: door.ColorText("CYAN ON BLUE")}}
 
- 	unselectMap := map[string]string{"BLUE": door.ColorText("BRI BLUE ON BLUE"),
 
- 		"BROWN":   door.ColorText("BROWN ON BLUE"),
 
- 		"RED":     door.ColorText("BRI RED ON BLUE"),
 
- 		"CYAN":    door.ColorText("CYAN ON BLUE"),
 
- 		"GREEN":   door.ColorText("BRI GREEN ON BLUE"),
 
- 		"MAGENTA": door.ColorText("BRI MAGENTA ON BLUE"),
 
- 		"WHITE":   door.ColorText("BRI WHITE ON BLUE"),
 
- 		"ALL":     door.ColorText("BRI WHITE ON BLUE")}
 
- 	selectMap := map[string]string{"BLUE": door.ColorText("BRI BLUE ON BLACK"),
 
- 		"BROWN":   door.ColorText("BROWN ON BLACK"),
 
- 		"RED":     door.ColorText("BRI RED ON BLACK"),
 
- 		"CYAN":    door.ColorText("CYAN ON BLACK"),
 
- 		"GREEN":   door.ColorText("BRI GREEN ON BLACK"),
 
- 		"MAGENTA": door.ColorText("BRI MAGENTA ON BLACK"),
 
- 		"WHITE":   door.ColorText("BRI WHITE ON BLACK"),
 
- 		"ALL":     door.ColorText("BRI WHITE ON BLACK")}
 
- 	m.SelectedR = MakeColorsRender(door.ColorText("BOLD CYAN"),
 
- 		door.ColorText("BOLD BLUE"),
 
- 		selectMap)
 
- 	m.UnselectedR = MakeColorsRender(door.ColorText("BOLD YEL ON BLUE"),
 
- 		door.ColorText("BOLD WHI ON BLUE"),
 
- 		unselectMap)
 
- 	for _, color := range DeckColors {
 
- 		m.AddSelection(color[:1], color)
 
- 	}
 
- 	return m
 
- }
 
- func RenderStatusValue(status string, value string) func(string) string {
 
- 	renderF := func(text string) string {
 
- 		var result string
 
- 		pos := strings.Index(text, ":")
 
- 		result = status + text[:pos] + value + text[pos:]
 
- 		return result
 
- 	}
 
- 	return renderF
 
- }
 
- // Display the SysOp settings in the Config/yaml file
 
- func DisplaySettings(d *door.Door) {
 
- 	d.Write(door.Clrscr + door.Reset)
 
- 	W := 35
 
- 	panel := door.Panel{Width: W,
 
- 		X:           5,
 
- 		Y:           5,
 
- 		Style:       door.DOUBLE,
 
- 		BorderColor: door.ColorText("BOLD CYAN ON BLUE"),
 
- 	}
 
- 	l := door.Line{Text: fmt.Sprintf("%*s", W, "Game Settings - SysOp Configurable"),
 
- 		DefaultColor: door.ColorText("BOLD GREEN ON BLUE")}
 
- 	panel.Lines = append(panel.Lines, l)
 
- 	renderF := RenderStatusValue(door.ColorText("BOLD YELLOW ON BLUE"), door.ColorText("BOLD GREEN ON BLUE"))
 
- 	for key, value := range Config {
 
- 		if key[0] == '_' {
 
- 			continue
 
- 		}
 
- 		key = strings.Replace(key, "_", " ", -1)
 
- 		l = door.Line{Text: fmt.Sprintf("%20s : %*s", key, -(W - 23), value), RenderF: renderF}
 
- 		panel.Lines = append(panel.Lines, l)
 
- 	}
 
- 	d.Write(panel.Output() + door.Reset + door.CRNL)
 
- 	press_a_key(d)
 
- }
 
- func Configure(d *door.Door, db *DBData) {
 
- 	menu := ConfigMenu()
 
- 	// deckcolor := "DeckColor"
 
- 	// save_deckcolor := false
 
- 	var choice int
 
- 	for choice >= 0 {
 
- 		d.Write(door.Clrscr)
 
- 		choice = menu.Choose(d)
 
- 		if choice < 0 {
 
- 			break
 
- 		}
 
- 		option := menu.GetOption(choice)
 
- 		switch option {
 
- 		case 'D':
 
- 			// Deck color
 
- 			colormenu := DeckColorMenu()
 
- 			d.Write(door.Clrscr)
 
- 			_ = colormenu.Choose(d)
 
- 			press_a_key(d)
 
- 		case 'V':
 
- 			// View settings
 
- 			DisplaySettings(d)
 
- 		case 'Q':
 
- 			choice = -1
 
- 		}
 
- 	}
 
- }
 
- func Help() door.Panel {
 
- 	W := 60
 
- 	center_x := (door.Width - W) / 2
 
- 	center_y := (door.Height - 16) / 2
 
- 	help := door.Panel{X: center_x,
 
- 		Y:           center_y,
 
- 		Width:       W,
 
- 		Style:       door.DOUBLE,
 
- 		BorderColor: door.ColorText("BOLD YELLOW ON BLUE")}
 
- 	help.Lines = append(help.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, "Help"),
 
- 		DefaultColor: door.ColorText("BOLD CYAN ON BLUE")})
 
- 	help.Lines = append(help.Lines, help.Spacer())
 
- 	copyright := fmt.Sprintf("Space-Ace (C) 2022 Red Green Software")
 
- 	help.Lines = append(help.Lines,
 
- 		door.Line{Text: fmt.Sprintf("%*s", -W, copyright),
 
- 			DefaultColor: door.ColorText("BOLD WHITE ON BLUE")})
 
- 	for _, text := range []string{"",
 
- 		"Use Left/Right arrow keys, or 4/6 keys to move marker.",
 
- 		"The marker wraps around the sides of the screen.", "",
 
- 		"Select card to play with Space or 5.",
 
- 		"A card can play if it is higher or lower in rank by 1.",
 
- 		"",
 
- 		"Enter draws another card.",
 
- 		"",
 
- 		"Example: A Jack could play either a Ten or a Queen.",
 
- 		"Example: A King could play either an Ace or a Queen.",
 
- 		"",
 
- 		"The more cards in your streak, the more points earn.",
 
- 	} {
 
- 		help.Lines = append(help.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, text)})
 
- 	}
 
- 	return help
 
- }
 
- func About() door.Panel {
 
- 	W := 60
 
- 	center_x := (door.Width - W) / 2
 
- 	center_y := (door.Height - 16) / 2
 
- 	about := door.Panel{X: center_x,
 
- 		Y:           center_y,
 
- 		Width:       W,
 
- 		Style:       door.SINGLE_DOUBLE,
 
- 		BorderColor: door.ColorText("BOLD YELLOW ON BLUE"),
 
- 	}
 
- 	about.Lines = append(about.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, "About This Door"),
 
- 		DefaultColor: door.ColorText("BOLD CYAN ON BLUE")})
 
- 	about.Lines = append(about.Lines, about.Spacer())
 
- 	copyright := fmt.Sprintf("Space-Ace (C) 2022 Red Green Software")
 
- 	about.Lines = append(about.Lines,
 
- 		door.Line{Text: fmt.Sprintf("%*s", -W, copyright),
 
- 			DefaultColor: door.ColorText("BOLD WHITE ON BLUE")})
 
- 	for _, text := range []string{"",
 
- 		"This door was written by Bugz.",
 
- 		"",
 
- 		"It is written in Go, understands CP437 and unicode, adapts",
 
- 		"to screen sizes, uses door32.sys, and runs on Linux and",
 
- 		"Windows."} {
 
- 		about.Lines = append(about.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, text)})
 
- 	}
 
- 	return about
 
- }
 
- func main() {
 
- 	var message string
 
- 	// Get path to binary, and chdir to it.
 
- 	binaryPath, _ := os.Executable()
 
- 	binaryPath = filepath.Dir(binaryPath)
 
- 	_ = os.Chdir(binaryPath)
 
- 	fmt.Println("Starting space-ace")
 
- 	rng := rand.New(mt19937.New())
 
- 	rng.Seed(time.Now().UnixNano())
 
- 	d := door.Door{}
 
- 	d.Init("space-ace")
 
- 	db := DBData{}
 
- 	db.Open("space-database.db")
 
- 	defer db.Close()
 
- 	// Use Real_name or Handle?  Or read config?
 
- 	db.User = d.Config.Real_name
 
- 	const config_filename = "space-ace.yaml"
 
- 	if FileExists(config_filename) {
 
- 		Config = LoadConfig(config_filename)
 
- 	} else {
 
- 		Config = make(map[string]string)
 
- 	}
 
- 	var update_config bool = false
 
- 	// Guessing at this point as to what settings I actually want.
 
- 	config_defaults := map[string]string{"hands_per_day": "3",
 
- 		"date_format":     "%B %d",
 
- 		"date_score":      "%m/%d/%Y",
 
- 		"makeup_per_day":  "5",
 
- 		"play_days_ahead": "2",
 
- 		"date_monthly":    "%B %Y"}
 
- 	// _seed
 
- 	_, ok := Config["_seed"]
 
- 	if !ok {
 
- 		// Initialize the seed
 
- 		Config["_seed"] = fmt.Sprintf("%d,%d,%d", rng.Int31(), rng.Int31(), rng.Int31())
 
- 		update_config = true
 
- 	}
 
- 	for key, value := range config_defaults {
 
- 		if SetConfigDefault(&Config, key, value) {
 
- 			update_config = true
 
- 		}
 
- 	}
 
- 	if update_config {
 
- 		SaveConfig(config_filename, Config)
 
- 	}
 
- 	starfield := StarField{}
 
- 	starfield.Regenerate(rng)
 
- 	starfield.Display(&d)
 
- 	d.Write(door.Goto(1, 1) + door.Reset)
 
- 	// Get the last call value (if they have called before)
 
- 	last_call, _ := strconv.ParseInt(db.GetSetting("LastCall", "0"), 10, 64)
 
- 	now := time.Now()
 
- 	db.SetSetting("LastCall", fmt.Sprintf("%d", now.Unix()))
 
- 	// Check for maint run -- get FirstOfMonthDate, and see if
 
- 	// records are older then it is.  (If so, yes -- run maint)!
 
- 	if last_call != 0 {
 
- 		d.Write("Welcome Back!" + door.CRNL)
 
- 		delta := now.Sub(time.Unix(last_call, 0))
 
- 		hours := delta.Hours()
 
- 		if hours > 24 {
 
- 			d.Write(fmt.Sprintf("It's been %0.1f days since you last played."+door.CRNL, hours/24))
 
- 		} else {
 
- 			if hours > 1 {
 
- 				d.Write(fmt.Sprintf("It's been %0.1f hours since you last played."+door.CRNL, hours))
 
- 			} else {
 
- 				minutes := delta.Minutes()
 
- 				d.Write(fmt.Sprintf("It's been %0.1f minutes since you last played."+door.CRNL, minutes))
 
- 			}
 
- 		}
 
- 	}
 
- 	left := d.TimeLeft()
 
- 	message = fmt.Sprintf("You have %0.2f minutes / %0.2f seconds remaining..."+door.CRNL, left.Minutes(), left.Seconds())
 
- 	d.Write(message)
 
- 	press_a_key(&d)
 
- 	mainmenu := MainMenu()
 
- 	var choice int
 
- 	for choice >= 0 {
 
- 		d.Write(door.Clrscr)
 
- 		starfield.Display(&d)
 
- 		choice = mainmenu.Choose(&d)
 
- 		if choice < 0 {
 
- 			break
 
- 		}
 
- 		option := mainmenu.GetOption(choice)
 
- 		// fmt.Printf("Choice: %d, Option: %c\n", choice, option)
 
- 		switch option {
 
- 		case 'P':
 
- 			// Play cards
 
- 		case 'S':
 
- 			// View Scores
 
- 		case 'C':
 
- 			// Configure
 
- 			Configure(&d, &db)
 
- 		case 'H':
 
- 			// Help
 
- 			h := Help()
 
- 			d.Write(door.Clrscr + h.Output() + door.Reset + door.CRNL)
 
- 			press_a_key(&d)
 
- 		case 'A':
 
- 			// About
 
- 			a := About()
 
- 			d.Write(door.Clrscr + a.Output() + door.Reset + door.CRNL)
 
- 			press_a_key(&d)
 
- 		case 'Q':
 
- 			choice = -1
 
- 		}
 
- 	}
 
- 	d.Write(door.Reset + door.CRNL)
 
- 	message = fmt.Sprintf("Returning to %s ..."+door.CRNL, d.Config.BBSID)
 
- 	d.Write(message)
 
- 	// d.WaitKey(1, 0)
 
- 	left = d.TimeLeft()
 
- 	message = fmt.Sprintf("You had %0.2f minutes / %0.2f seconds remaining!"+door.CRNL, left.Minutes(), left.Seconds())
 
- 	d.Write(message)
 
- 	left = d.TimeUsed()
 
- 	d.Write(fmt.Sprintf("You used %0.2f seconds / %0.2f minutes."+door.CRNL, left.Seconds(), left.Minutes()))
 
- 	fmt.Println("Exiting space-ace")
 
- }
 
 
  |