aboutsummaryrefslogtreecommitdiff
path: root/main.go
blob: 2eabd7319880aa0b8faff0ac6c701b9dfd68f4a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main

import (
	"fmt"
	"math/rand"
	"os"
	"time"

	"git.kiefte.eu/lapingvino/prompt"
)

func klariguLudon(min, max, skip int) {
	fmt.Printf(`Bonvenon ĉe "Kaptu la muson"

La celo de la ludo estas diveni numeron de %d ĝis %d.
Vi povas provi tion unu post la alia.
%s
Se la numero fariĝas pli alta ol %d, ĝi reiras al %d.
Se la numero fariĝas malpli alta ol %d, ĝi reiras al %d.
Multan sukceson!

`, min, max, skipDoes(skip), max, min, min, max)
}

func skipDoes(skip int) string {
	switch {
	case skip > 0:
		return fmt.Sprintf("Tamen atentu! La numero povas post ĉies vico ĉu %d supreniri, ĉu tiom malsupreniri, ĉu resti sama.", skip)
	case skip == 0:
		return fmt.Sprint("Vi elektis ke la numero ĉiam restu la sama.")
	case skip < 0:
		return fmt.Sprintf("Vi elektis veran defion. La numero povas post ĉies vico en hazarda kvanto de maksimume %d supreniri, ĉu samkvante malsupreniri, ĉu resti la sama.", -skip)
	}
	panic("This should never happen.")
}

func askPlayers() (n int) {
	fmt.Print("Kiom da ludantoj estas? ")
	n = prompt.MustRead[int]()
	if n < 1 {
		return 2
	}
	return n
}

func askNames(n int) (names []string) {
	for i := 1; i <= n; i++ {
		fmt.Printf("Ludanto %d, kiel mi nomu vin? ", i)
		names = append(names, prompt.MustRead[string]())
	}
	return names
}

func getNumber(min, max, skip int, guessed chan bool) (nchan chan int) {
	nchan = make(chan int, 0)
	go func() {
		i := rand.Intn(max-(min-1)) + (min - 1)
		s := rand.Intn(3) - 1
		skipn := skip
		if skip < 0 {
			skipn = rand.Intn(-skip)
		}
		for {
			select {
			case nchan <- i:
			case <-guessed:
				guessed <- true
				return
			}
			i += s * skipn
			switch {
			case i > max:
				i = min
			case i < min:
				i = max
			}
		}
	}()
	return nchan
}

func play(name string, number int) (won bool) {
	fmt.Printf("Estas la vico de %s: kiu numero estas? ", name)
	guess := prompt.MustRead[int]()
	switch {
	case number == guess:
		fmt.Println("Prave, la numero estas", number)
		return true
	case number > guess:
		fmt.Println("Ne, la numero estas pli alta ol", guess)
	case number < guess:
		fmt.Println("Ne, la numero estas pli malalta ol", guess)

	}
	return false
}

func again() bool {
	for {
		fmt.Print("Ĉu ludi denove, jes aŭ ne? ")
		answer := prompt.MustRead[string]()
		switch answer {
		case "jes":
			return true
		case "ne":
			return false
		}
	}
}

func main() {
	rand.Seed(int64(time.Now().Nanosecond()))
	min, max, skip := 1, 100, 1
	switch len(os.Args) {
	case 0:
		panic("This shouldn't happen: os.Args is an empty slice.")
	case 1:
		fmt.Print("(Vi ludas kun la defaŭltaj valoroj. Se vi volas pli grandan defion, provu ŝanĝi la parametrojn! Nur unu parametro indikas la plej altan numeron, se vi indikas pli tio estas sinsekve minimumo, maksimumo, saltogrando. Negativa saltogrando hazardigas la saltograndon je ĝia absoluta valoro. Bonan muskaptadon!)\n\n")
	case 2:
		fmt.Sscan(os.Args[1], &max)
	case 3:
		fmt.Sscan(os.Args[1]+" "+os.Args[2], &min, &max)
	default:
		fmt.Sscan(os.Args[1]+" "+os.Args[2]+" "+os.Args[3], &min, &max, &skip)
	}
	klariguLudon(min, max, skip)
	players := askPlayers()
	names := askNames(players)
	guessed := make(chan bool)
	numbers := getNumber(min, max, skip, guessed)
	for {
		for _, name := range names {
			select {
			case number := <-numbers:
				won := play(name, number)
				if won {
					fmt.Printf("Gratulon %s, vi gajnis!\n", name)
					if again() {
						guessed <- true
					} else {
						fmt.Println("Ĝis revido!")
						return
					}
				}
			case <-guessed:
				numbers = getNumber(min, max, skip, guessed)
			}
		}
	}
}