compilation fixes
[intricacy.git] / notes / metagame
blob992b607b1fb41af0d6c5c6a9922df9ac093af7b5
1 Overgame:
2 (writing under the influence of Castle Doctrine (although I'd been planning
3 something like this since long before I heard of CD!))
5 The players are the members of the Guild of Locksmiths. A venerable tradition
6 in this guild has the honour of a member determined by the number of silver
7 hook picks they possess. Tradition further has it that members must store
8 their collection of picks in coffers in the main hall of the guild, locked
9 behind fiendish yet pickable locks of their own devising. Members may freely
10 attempt to pick their fellows' locks, using their silver hooks, and take the
11 picks found within. New members start with 5(?) hooks. If a hook gets stuck
12 during an attempt on a coffer, it goes in that coffer.
14 Problems: there needs to be some cost to producing your own locks, or optimal
15 play would have you put each hook in a separate well-locked coffer, leading
16 to tiresomeness. And having every lock be maximally complicated would be a bit
17 boring - there should be costs associated to making complex locks. Also,
18 there's every incentive to not bother making a proper lock until you've made
19 some winnings, and to keep starting new characters until you have.
21 So forget the silver hooks - replace with a generic guild-internal currency,
22 which can be spent on picks and on coffers and lock components.
24 To deal with the latter problem: could make it such that lock designs are
25 one-offs - you can't edit it once it's complete, you can't pick other
26 locks until you have designed a lock to store any gains behind, and you can't
27 design further locks until your existing locks have withstood a few pick
28 attempts. This would also do something to minimize the cd-style "just one more
29 little edit" addictiveness.
31 To prevent cheating, we should give the client every possible convenience
32 feature. If there's no hidden information, then that includes undo. With undo, 
33 we need a time-limit for there to be any challenge.
35 Considering hidden information:
36     How to ensure that locks are nonetheless fun, in the way cd's often
37     aren't?
39     It would be thematic to have vision based on sound and touch: so every time a
40     part of the lock moves, it is shown, and everything in the vicinity of your
41     tools is shown. 
43     But however we do it, hidden information of a kind which prevents
44     undo-cheating will surely end up allowing traps avoidable only through
45     lucky guessing. Hrm.
47 So instead aim to have the mechanics sufficiently complicated that locks can
48 be made which are not susceptible to brute-force attacks, even ones guided by
49 an undo-wielding, keysmashing, unthoughtful human. With 15 possible moves each
50 turn, that perhaps isn't so implausible.
52 We can also make the time limit more severe by having a turn limit as well as
53 a time limit, and then using a fischer-clock system for the time limit, such
54 that you have to commit to some moves reasonably quickly. That would make undo
55 much less useful (although it should still be incorporated into the official
56 client, even if not well advertised). Turn and hence time limit would be, say,
57 triple the number of turns it took the creator when sey demonstrated
58 solvability.
60 Foiling sock-puppet attempts to get around the "one attempt per lock per
61 player" rule: don't give the players free choice over which locks to attempt.
62 Either only give them access to some random subset of the available locks, or
63 perhaps don't let them pick locks at all - instead they just indicate the
64 general hardness they want to go for.
66 Problem: if the complexity of a lock is bounded by cost, we should expect
67 cheap locks, however ingenious, to be consistently beatable by experienced
68 players. Solution: make sure this isn't true! Also: make the wager you stand
69 to lose if you fail to pick a lock be based on your own wealth?
71 After further thought, I am favouring equality in locks. You pay for the
72 coffer; locks are free. But locks are severely limited in size (say,
73 sufficiently that they can be displayed on an 80x24 terminal...), so it will
74 take some cunning to make a difficult lock.
76 You can design locks whenever you want, and maintain a library of designed
77 locks linked to your account. You start with a coffer, and new ones cost some
78 certain number of picks (10?). You can store as many picks as you like in a
79 coffer, but you might be wise to spread the risk.
81 It is intended that each human has just one account. To ensure this, new
82 players are required to undergo initiation before they can start picking
83 others' locks.  This is essentially a tutorial, getting you to pick some
84 predesigned locks. Furthermore, fresh initiates may not try high-level player
85 locks.
87 If a player runs out of silver picks: if sey has spare coffers, one is sold
88 back to the guild; else, sey is gifted valueless iron picks to try seir luck
89 with, say 5 per day (doled out all at once). You must use silver picks if you
90 have any. You start the game with 5 iron and 5 silver.
92 There are also valueless practice locks you can test your skills on without
93 wagering a pick - these should include a "hall of fame" of the locks which
94 withstood the most pick attempts before being picked.
97 Alternatively: can we judo sock puppets? Design the metagame such that there's
98 no advantage to having multiple accounts?
101 Misc:
103 http://www.haskellforall.com/2012/07/first-class-modules-without-defaults.html 
107 Maybe drop the chess clock in favour of a simple time limit depending on lock
108 complexity, with full undo? Easier to implement (could use http, or even email
109 (although delays would be a problem, as would forged timestamps)), and less
110 stressful. Would mean that simple traps lose importance - not sure if that's
111 good or bad.
113 Going this route, we could even copy CD's technique of checking that the
114 submitted solution really is one to be run as a batch job - meaning that the
115 server can run as a cgi script on sdf, with the checking being done as a
116 cronjob on legonz.
119 Architectural musings:
120 The client exists to
121     (i) design and test lockfiles
122     (ii) solve locks
123     (iii) view solutions
124 so inputs and outputs are lockfiles and command-sequences.
126 Remark: given undo, there's not much point in uploading failed attempts -
127 only the whole undo tree would really show anything, and usefully displaying
128 that is infeasible. There's always the possibility that I'll want to revert
129 to the chess clock setup, so aim to leave the possibility of uploading and
130 viewing failed attempts.
132 Tempting to keep the client wholly local, letting the user use other means
133 (http, email, ftp, whatever) to communicate files with the server(s). But
134 perhaps that would be too annoying.
136 Alternatively, we have some nice simple cgi script as the server, and the
137 client uses curl or whatever to talk to it. So we still deal locally with
138 files, we just automate the process of uploading and downloading the files.
140 So we have a few basic high-level operations for the client, which should be
141 launchable independently with appropriate command-line options, but which also
142 get appropriately twisted together in the default mode:
143     edit/create lockfile (producing canonical lockfiles)
144     play lock (taking lockfile, producing solution)
145     view solution (taking lockfile and solution)
147 Metagame interactions with the server:
148     buying coffers and selecting locks for them
149     adjusting distribution of picks between coffers
150     choosing coffers to try to crack
152 Tempting to have these all done purely with cgi+html. But recall just how
153 horrible html interfaces are.
155 Instead, I think I like the idea of using a simple textual interface for
156 these, with displays of your locks mixed in where appropriate, which can
157 easily be uniform over UIs (recall that in text-mode, a lock takes up only
158 25 out of 80 columns, and in SDL we can scale arbitrarily). But let's not
159 worry about details of the UI for now. Suffice to say I see that it could be
160 done quite neatly - and that having the ability to display the locks is
161 another good reason to make it all part of the same client.
163 The server needs to handle:
164     sending coffer status - including any solution files
165     accepting coffer updates, including new locks
167 Do we need a database? Or will a directory structure do?
168 Server:
169     locks/LOCKIDENTIFIER/{lockfile,creator,solution,attempts/,picks}
170 Client:
171     no need to use the file system, except for your collection of lockfiles.
172     The rest can be kept in memory.
174 On the server, locks are named after sequential numbers.
176 But then Jason Rohrer wrote this paeon to sql, which made me reconsider:
177 http://thecastledoctrine.net/forums/viewtopic.php?pid=2566#p2566
179 mysql vs sqlite: main difference seems to be that sqlite write-locks the whole
180 database when any part of it is written to, while mysql is cleverer. sqlite
181 should be fine for this project, I'm sure.
183 -----
186 Remind me: why is this idea of having a metagame a good one and not a silly
187         one?
188     Answer: because the whole point is to explore the outer reaches of
189         complexity within the space of possible puzzles - which given the hard
190         restriction on lock size, means exploring the extremes of intricacy.
191         For this, we need clear motivation from puzzle designers to design the
192         hardest puzzles they can. This is the point of the metagame.
194 -----
196 Simplifying the metagame:
197 One active lock per player.
199 No penalty for changing the lock you're using.
201 Players are wholly anonymous (*not* pseudonymous) and before agreeing to try a
202 lock you're told only the approximate number of picks it protects. This way
203 there's no real way to abuse multiple accounts, because you can't really
204 transfer picks between accounts.
206 So although having a single account should be the default, we can allow the
207 addicted to create extra.
209 Actually no, this doesn't work at all - we *have* to avoid the same player
210 getting two stabs at a lock. Hrm.
212 Note there *is* anyway a potential for abuse if one person owns a significant
213 proportion of the accounts... I'll just have to watch out for that.
215 Given anonymity, no need for usernames - a single secret identifier will
216 suffice.
218 Handling revenge with anonymity: just make it an explicit option, a key/button
219 when watching a replay. But maybe revenge doesn't fit this game anyway.
221 But maybe the *locks* should get (code)named - at least the successful,
222 publically displayed ones? That way people can talk about them in sidechannel
223 discussions, and there can even be publically accessible urls for them.
224 No need to let the creator choose the name (a recipe for profanity and
225 SQL-injection...), can use a wordlist.
227 -----
229 Need to take seriously this exploit:
230     create two accounts (can't hope to prevent this)
231     log in with account 1, try a load of locks
232     solve them in your own time
233     log in with account 2, knowing the solutions to lots of locks.
235 This isn't preventable, nor is it really detectable. So it's a fatal flaw with
236 the current design.
238 So ditch the idea that a user can only try a lock once.
240 So it seems we're led to: a race to be the first to solve a lock.
242 So like the current design, but without the time limit, and with no second
243 prize (lest the same player with multiple accounts take all the prizes).
245 Obvious worry: solving locks, particularly given undo, is so much quicker than
246 creating them that it'll be rare that there are any unsolved locks available.
248 This may not be too bad if the userbase is large and active enough. If I spend
249 an hour designing a fiendish lock which someone then picks in ten minutes,
250 that's arguably not a problem if at least five others were also trying to pick
251 it during those ten minutes. If the solver is the only person who ever sees
252 it, we have a decided imbalance.
254 But maybe this is overly simplistic - as long as the design stage is
255 sufficiently painless and engaging, spending most of your time there shouldn't
256 be a problem. Still, it's an argument e.g. for keeping the balls, making
257 greater intricacy easier to achieve. Possibly relaxing size limits would do
258 this too (on the basis that squeezing an intricate lock into a small space
259 takes extra ingenuity).
261 We need to think about incentives. Unoriginality - e.g. just using the same
262 lock over and over again, or copying someone else's - is naturally discouraged
263 since such a lock is likely to be solved very quickly. (Note that we don't
264 have to worry about someone copying a lock design before solving it
265 themselves, thanks to the self-test.)
267 We need to set things up to foil another obvious exploit: setting a lock with
268 one account and then solving it with another. It's ok for this to result in a
269 flow of points, but it shouldn't be a net gain if the solution is given
270 quickly. I suppose it won't be possible to foil this strategy completely,
271 since for a decently hard lock we do want to reward both setter and solver...
272 but it is at least relatively easy to detect. We could also try anonymisation
273 techniques (which would have to include adding a random delay, invisible to
274 the setter, between a lock being set and it becoming available...) but there
275 will anyway be a systematic advantage to be gained from sock-puppetry.
277 Cunning solution to all of these problems: information as currency! See below.
279 ------
281 Information-based economy
282 =========================
284 Cryptocurrencies and attempts by backwards-looking business-types aside, an
285 information-based economy differs crucially from a resource-based one, in that
286 information can be copied.
288 This deals with all sock-puppet problems.
290 How I'm thinking this should work:
292 When you solve a lock, you take notes. You store your notes behind your lock.
293 When you crack a lock, you take a copy of everything behind it, adding them to
294 your own stash. Your "score" is the number of locks for which you have a
295 solution (whether discovered yourself or copied).
297 Consequences:
298     It is important to set a strong lock, to protect the secrets to which you
299     become privy. Doing so adds something to the game "economy" (weak
300     metaphor), which dissipates slowly and most likely only after the lock has
301     been independently cracked by a fair few players. 
303     Problem: optimal play would have you change your lock as soon as it's been
304     cracked, since knowledge of how to crack it will spread exponentially, so
305     it will soon become useless for protecting new secrets. (Note that for the
306     secrets it originally protected, it's too late - they will spread
307     exponentially anyway.) This could prove tiresome, and more to the point
308     will mean a lock doesn't provide as much entertainment for solvers.
309     Solution: don't allow changing a lock or removing what it guards, but do
310     allow setting a new active lock behind which newly acquired secrets will
311     go.
312     Problem with solution: now optimal play is to create a new lock for each
313     lock you crack, leading to exponential growth in number of uncracked
314     locks.
316 Thought: notes needn't give full solutions, they could just give hints - e.g.
317 a snapshot of the gamestate at a random point during the solution. Problem
318 with that: players could take a deliberately contorted path to the solution,
319 such that a random snapshot might well be misleading.
320 Or: similar, but automated - say you need to gather notes resulting from n
321 independent solutions of a lock, and then you automatically solve the lock.
324 Revised version:
325 ----------------
326 Each time you solve a lock, you take "notes". In order to "claim" your
327 solutions, you must design locks of your own behind which to secure your
328 notes. Behind each lock goes n notes. Whenever you claim a solution to a lock,
329 you get to see the n notes it secures. Once you have seen k notes on the same
330 lock, you automatically solve it (and get to see the notes it secures, which
331 may result recursively in further automatic solving).
333 Your "score" is the number of locks you have claimed solutions for - direct or
334 automatic. Locks you have set yourself count towards this.
336 Effects of parameters:
337     b:=n/k is the branching number: solving a lock lets you solve on average
338     b^t of the locks t layers back. We want b>1, so old locks effectively lose
339     value over time. 
341     k is the "fragmentation index", and controls the relative value of
342     designing and solving locks.
344     n=3, k=2 seems like a decent first thing to try, twiddling later if it
345     seems appropriate.
347 Subtleties:
348     The tougher locks will be more valuable, since solving one will increase
349     your relative score for longer. So it's in your interest to put your notes
350     on them behind your own most ingenious locks. So the hardest locks should
351     keep their value for the longest.
353     We shouldn't force players to claim their solutions as soon as possible,
354     because that could be got around by working out how to solve locks but
355     avoiding actually doing so until you're ready to claim them, and also
356     because players who enjoy solving might not bother to design a sound lock.
357     But note that there's a strong incentive to claim quickly - the value of a
358     solution depreciates exponentially as others solve the lock.
360     What I mean by 'value' of a solution should maybe be spelt out: solving a
361     new lock gives you (on average) b^t solutions of locks of "age" t, where
362     (as discussed above) easier locks age much faster than hard ones. So by
363     having score be a simple count of the number of locks you have solutions
364     to, we get this natural depreciation.
365     
366     Note that this means that coming in late as a new player, you can catch up
367     with the old hands quickly by solving some of the latest locks (and
368     there'll be a nice rich bank of old locks to study if the new ones are too
369     hard).
371 Potential for cheating:
372     Devise a tricky lock, and learn how to solve k existing locks.
373     Create a whole cupboard of sock puppets. Have each puppet solve those k
374     locks and put the notes behind that tricky lock. Then have your main
375     account solve each of these many instances of that tricky lock. Result:
376     your main account gets a cupboard of points. Arse.
378 Another problem:
379     You could deliberately solve earlier locks before the later ones, to
380     maximise the number of notes you get and hence the number of locks you can
381     set. This is grinding, and rational. That's a problem.
383 Recovery:
384     What happens if we just explicitly allow that kind of "cheating"? That
385     comes down to: allow setting a lock which secures nothing, with you still
386     getting a point for it. Answer: spam. Hrm.
389 Another separate worry:
390     What about public accounts? If a whole load of players use the same
391     account, it would end up as a spoilerbank. Could try to detect multiple
392     simultaneous uses, I guess.
394 Rethinking motivation:
395     Aim is to motivate designing locks which can't be easily solved by the
396     current playerbase.
398     Simplest way to do that: each player designs a lock, and they're ranked
399     according to how long they've remained unsolved. But that gives locks a
400     very short life - solved once then valueless. And there wouldn't be much
401     interest in trying to solve any lock other than the currently top-rated
402     one. So something more subtle is required.
404     Designing locks as a means to protect your winnings from solving them is
405     a natural and appealing setup. Given sock-puppets, these winnings must be
406     of a kind you can only obtain from other humans. Which has to mean
407     solutions to puzzles, which you yourself might not be able to solve. We
408     want these puzzles to be player-produced, so naturally they should be the
409     locks themselves. So the basic design above seems pretty much inevitable.
411     The tricky bit is to motivate trying to keep your solutions secret, while
412     avoiding potential for abuse. If we simply motivate having solutions
413     others don't, we clearly motivate sock-puppetry. We want to motivate
414     having solutions *to the locks of other humans* which others don't.
416     How about if we drop the idea of a linear scale. A dominates B iff A can
417     crack more of B's locks than can B A's. The point being that you're not
418     going to care about dominating your sock puppets. Problem: you don't
419     really care about others dominating those you dominate, either, so won't
420     care about protecting your secrets.
422     But consider Ultra. You want to keep your solution to a lock to yourself
423     because you don't want the owner of the lock to stop using it. So we need
424     a cost associated to setting up a new lock, such that you're motivated to
425     keep using an old one until it's been too thoroughly compromised.
427 New version
428 -----------
430 You're allowed at most l active locks at any time. To declare a solution
431 to a lock, you put your notes on it behind one of your active locks. If
432 you deactivate one of your locks, then its solution along with all notes
433 it secured become common knowledge. You have access to all public
434 knowledge notes and to all notes secured by locks to which you have a
435 declared or automatic solution, and having access to k notes on a lock
436 gives you an automatic solution to it. There is no absolute scoring;
437 rather, A scores a point against B for each of B's locks to which A has a
438 solution, and each player sees other players ranked according to relative
439 score. Optionally, you can get fractional points for having notes on a lock.
441 Player motivation:
442     If too many players have solutions to one of your active locks, you'll
443     want to ditch it. So if you have a solution to someone's active lock, you
444     won't want too many others to get solutions to it. So you want to protect
445     your notes. So you will put your most valuable notes behind your hardest /
446     least compromised lock. So notes to harder locks will be more valuable.
448     Note that it can be rational to put notes behind your more compromised
449     locks, in order to spread risk and not make your most valuable lock too
450     tempting a target. For this to work, it should be public knowledge what
451     notes are secured by each of your locks.
453 Parameters:
454     Increasing l lengthens the active life of a lock. It also makes the
455     scoring finer.
457     Large k reduces the importance of lock compromisation, and in particular
458     also lengthens the active life of a lock.
460     l=3 k=3 sounds good.
462 Potential for abuse:
463     Sock puppets:
464         You can set locks as a sock-puppet and solve them with your main
465         account, but this will affect only the relative score between these
466         two accounts.
468         You could scare someone into thinking their lock is utterly
469         compromised by solving it with many accounts. But this wouldn't be
470         rational - if they ditch the lock, its solution and contents become
471         public knowledge, so your situation is only worsened.
473         You could be a complete arse and create lots of mirror accounts, which
474         copy your every action. With enough mirrors, players wouldn't waste
475         their time solving every copy of your locks, so whichever account you
476         decide is the real one would get an advantage. This could be made more
477         difficult with IP checks and checking for identical locks, but can't
478         really be prevented. But the only motivation for doing this is to show
479         off that you can break the game if you want to, so hopefully a "yes
480         yes, well done" followed by manual purging of the accounts would
481         suffice.
482         
483     Shared accounts and other conspiracies:
484         We can't prevent these. Discouragement and banning discovered accounts
485         should suffice.
487 Possible complications:
488     Could incorporate variable locksize by allowing one large lock in place of
489     two normal sized locks, and two small locks in place of one normal.
491     Hints: having 0<n<k notes could give you hints on solving the lock. To
492     minimise potential for planting false information, this should consist of
493     views of the final, solved state of the lock, as obtained by the solver.
494     For n=k-1, this should be the whole final state; for smaller n, some part
495     of it.
497 Other remarks:
498   Locksize(s) for new locks should be server-configurable (so I can fiddle
499   with it as necessary).
501   I worry that the design rewards people for playing more as well as for
502   playing better. But there's no unabusable way to restrict it - you can
503   always log in with sock puppets, obtain some locks, spend however long you
504   need cracking them, and then use this information with your main account.
507 ------
509 Metagame UI
510 ===========
512 Even with relative scoring, sock-puppetry would be an annoyance to other
513 players. So showing anything like a total of the relative scores would
514 be a bad idea - it could motivate a player to sock-puppet just to boost
515 that total, even if it's only going to be shown to sem.
517 So relative scores should be shown one-by-one, not tallied.
519 But for each player, I think it is important to give a single number for
520 the relative score, something you're directly motivated to increase,
521 rather than just describing the details of how you relate to that
522 player. The relative score could be called something like the "advantage
523 over" the player; recall it's calculated as
524 [number of seir locks I can solve] - [number of my locks sey can solve].
525 Forget the idea of fractional score, that would just complicate things.
527 When you create an account, you choose a three-character codename.
529 The main metagame display will show your three active locks; below each
530 lock is listed the locks notes on which are secured by the lock, above
531 each lock information on who has solved it (or a warning if its solution
532 is common knowledge), and somewhere on the screen a random selection of
533 other players who have no particular relation to you. In all cases, the
534 player concerned will be represented by seir codename along with your
535 score relative to sem (with both being colour coded for sign and
536 magnitude of the score, so +3 is bright green etc). Selecting a player
537 will switch to a version of the main view for sem, showing seir locks
538 and notes and notednesses, and some text of the form "You hold
539 a slight/substantial/absolute advantage over ZGZ" or "ZGZ holds
540 a slight/substantial/absolute advantage over you" or "You are even with
541 ZGZ", with the adjective being colour coded with the same colours as the
542 numbers. Then some detail on which of seir locks you've solved and which
543 of yours sey's solved.
545 (Selecting one of seir locks will let you try to solve it. Selecting one
546 of your locks gives you the option of deactivating it and replacing it
547 with one of the locks in your library; designing locks to go in your
548 library is done in a separate interface.)
550 Hopefully this will be enough to encourage players to try to increase
551 the numbers.
553 Note in particular that if some of your locks have common-knowledge
554 solutions (i.e. if three players have solved the lock and then
555 deactivated the locks which secured their notes on your lock) the
556 randoms shown to the right will all be red.
559 Monochrome mockup for the curses version of this in an 80x24 terminal
560 follows. Graphical version will be similar, but the actual locks will be
561 shown (the graphics for that being arbitrarily scalable). For
562 terminals which are a bit larger, the same can be done in the curses
563 version. The words in the centre are names for the locks, given by and
564 seen only by yourself (these are actual names of locks in my own
565 library).
567 --------------------------------------------------------------------------------
568                                       ZGZ
569                                   (That's you)
570                          |                           |
571                          |                           |
572       Cracked by:        |       Cracked by:         |        Cracked by:
573                          |                           |
574     FKU -2    +++ +1     |        Everyone!          |         [no-one]
575                          |                           |
576                          |                           |
577            A             |            B              |            C
578         cannon           |         nameless          |         tricksy
579                          |                           |
580      Holds notes on:     |      Holds notes on:      |       Holds notes on:
581                          |                           |
582         C:NGS +2         |   A:NGS +2    C:+++ +1    |    B:NGS +2  B:+++ +1
583                          |                           |    A:#$% 0   C:ARG +1 
584                          |                           |         A:AAA 0
585                          |                           |
586   Random players:   CNT -1   ^&^ -1   #Z# +1   +3! -1   YHW 0
587         [more random players; I can't be arsed to come up with more codenames]
589   UNDECLARED solutions:   B:BLL -1  A:#Z# +1
591   x: examine player  c: change lock  d: declare solution  e: edit locks  q: quit  
592 --------------------------------------------------------------------------------
594 If I then type 'x', it will prompt me for a codename (which doesn't have
595 to be one displayed on the screen); if I type '#Z#' I'll get the
596 screen below. (In graphical mode, I could achieve the same effect by
597 clicking on '#Z#' wherever in the above.)
599 --------------------------------------------------------------------------------
600                                       #Z# +1
601                      You hold a slight advantage over #Z#
602                          |                           |
603                          |                           |
604       Cracked by:        |       Cracked by:         |        Cracked by:
605                          |                           |
606         BLA -1           |  NGS +2   YHW 0   ARG +1  |         Everyone!
607                          |           ZGZ -           |
608                          |                           |
609           A              |             B             |             C
610   Cracked but UNDECLARED |   Cracked! (from notes)   |   Cracked! (from notes)
611                          |                           |
612      Holds notes on:     |      Holds notes on:      |       Holds notes on:
613                          |                           |
614         A:NGS +2         |     B:NGS +2  A:+++ +1    |    B:YHW 0   C:ZGZ - 
615                          |                           |         B:+3! -1
616                          |                           |
617                          |                           |
618      You have cracked 2 of #Z#'s locks; #Z# has cracked 1 of your locks.
619         A:ZGZ - 1 note read by #Z#
620         B:ZGZ - cracked directly by #Z#
623               x: view player  c: crack lock  m: view ZGZ  q: quit  
624 --------------------------------------------------------------------------------
626 Note that the scores shown here are still those relative to me, not to
627 #Z#. 
629 In this example, I have read three notes on each of B and C, which is
630 why I've cracked them; if I had read only 2 notes, it would say "read
631 2 notes" in place of "Cracked! (from notes)".
633 Note that players who have cracked a lock from notes appear in the
634 "Cracked by:" section, undifferentiated from those who cracked it
635 directly. If there are too many to display, a random selection is
636 displayed (ending with "and N more").
638 Note that I'll use colour to pick out the important words where I've
639 written out blocks of text. I'll probably also use consistent colours
640 for 'A', 'B', and 'C' when they are indicating locks.
642 Note also that I've started using the terminology "cracked" rather than
643 "solved". Obviously this is by analogy with crypto... not sure how
644 appropriate it is!
647 Thoughts on automatically gauging difficulty of a lock, so as to allow a "hall
648 of fame" for the best retired locks: basing it on how long the lock lasts
649 isn't much good, since if no notes are put behind, it could just survive in
650 obscurity. Anything involving seeing how many attempt a lock would be
651 gameable. Similarly anything involving counting notes. Hmm.
653 Maybe no need for that. Just let players see the retired locks of other
654 players, and maybe have players decide which of their retired locks they're
655 most proud of so should be shown first. Hmm. Or maybe just ignore this problem
656 for now.
659 ------
661 Architecture
662 ------------
664 Size estimates:
665     metagame stuff:
666         for each user
667             codename: C bytes
668             serial numbers for active locks: 3*L bytes
669             *who's solved them (and whether directly): S*(C+1) bytes
670             how many notes on each lock are public knowledge: 3 bytes
671             notes declared: N*(C+L+1) bytes
672             *notes read: R*(C+L) bytes
673         C=3.
674         L=3 is plenty.
676         This information, along with public knowledge, suffices to display the
677         info screen for the user.
679         Starred entries can theoretically be computed just from knowing all
680         the declared notes, but not cheaply.
681     lock:
682         Show + gzip: ~1K
683         based on ascii representation: 30<2^5 possibilities per cell, 175 cells
684             875 bits; 110 bytes
685         Data.Binary + gzip: ~450 bytes. Hrm.
687     solution: 10<2^4 commands, say average 100 moves: 50 bytes.
688         gzipping might work on it.
690 Let's dream big, and say we want to be able to support 5000 players. With
691 three locks each, that's about 1.5M of lock data.
693 Meanwhile, with S=30, N=20, R=40, we get 3+9+90+120+240 =~ 460 bytes per
694 player for metagame data. So around 2.5M.
696 We don't want the server to have to push 4M of data to each of 5000 players.
698 So on-demand is the way to go. Locks and solutions are permanent, so can and
699 should be cached permanently. User entries can be too - but checked for
700 updates whenever displayed.
703 Communication we want to support:
704     client->server
705         Setting locks
706         Declaring solutions
707             these can block on verification
708     client<-server
709         Updating user info
710         Get lock
711         Get (partial) solution
713 We should send only deltas where possible. So user info and PK are versioned
714 with serial numbers; the server stores the latest version and the previous N
715 deltas, and if requested an update from a recent enough version sends only the
716 deltas, else sends the whole latest version.
718 Sounds like we're hand-rolling, then. Fine by me!
720 Server consists of a simple CGI script to handle incoming locks and solutions
721     verifies account ownership
722     fires up intricacy to verify solutions
723     updates files appropriately
725 For getting stuff off the server, we can use straight HTTP for locks (which
726     are public knowledge and don't change). For the rest, we can use a CGI
727     script, which can send deltas when appropriate and verify passwords and
728     privs when requesting solutions.
730 Updates:
731     On solution declaration:
732         Add as read note for all who have access to the lock it's stored
733         behind; this may result in that user getting three notes (public
734         notes included), leading to that user reading extra notes.
735     On lock change:
736         All notes behind the lock become public knowledge. These locks may
737         themselves become public knowledge, or become cracked by those who
738         have read sufficient notes on them, which as above results in them
739         reading notes.
741 Security:
742     No need for TLS; just encrypt all requests to the server's public key.
743     One such request is 'reserve codename', and we send a password with that
744     and all future requests requiring authentication.
746     Fine to ignore this for now, and just send everything in the clear. Can
747     add crypto later.
749 PoW:
750     Would be easy to require a little proof of work when reserving a
751     codename... but I don't think it's a good idea.
754 -----
755 Caching - implementation details
756 --------------------------------
758 Use STM. When the UI wants a userinfo, we
759     infoTV <- atomically $ newTVar (Nothing :: Maybe UserInfo)
760     forkIO getUserInfo infoTV
761 then record infoTV in the UI state, and then whenever we want to draw it or
762 whatever, we get at it like this:
763     atomically $ readTVar infoTV >>= maybe retry return
764 meanwhile, the 'getUserInfo' thread first looks in the cache and writes any
765 result to infoTV, and then consults the server and updates infoTV (and the
766 cache) if appropriate.
768 Neato.
770 The cache can use the Database module, first cding to a dir named after the
771 server (hostname[:port]).
773 Implemented.
775 But to know what colour to draw a codename, we need to calculate the relative
776 score, which involves having the userinfos of both players.
779     * we should put any cached info in the tvar right from the start, so we
780         don't redraw the screen after each file is read from the disk;
781     * we really need a versioning mechanism for userinfo, with the server
782         only sending over the userinfo when the cache is stale (and preferably
783         only sending diffs)
784     * we need some nice abstract mechanism for handling stuff calculated from
785         tvar-held information
786     * arguably we should cache the calculated scores in memory, recalculating
787         only if we get new pertinent information from the server
788     * to minimise server-hammering, we should have a timeout before which a
789         uinfo won't be checked for freshness when it's being used only for
790         score calculation.
791         (System.Time.TOD secsSinceEpoch _ <- System.Time.getClockTime)
794 -----
795 Metagame UI architecture
796 ------------------------
798 IMMeta.
800 Single view for everything:
801     Server, along with indicator of pending requests, with the option to
802     select cache-only mode.
804     Lock library, with currently selected lock name shown, with preview in SDL
805     mode, and buttons/keys to change, to edit, and to set as current lock - to
806     create a new one, first set the name to something not yet in the library.
808     Tutorials.
810     Currently viewed codename. If not yet authenticated: if server says
811     codename is free, option to register it; else, option to authenticate.
812     After successful auth/reg, send the auth with all future server requests.
814     Userinfo, if appropriate.
816     Message/Promt line.
818 In curses mode, this comes down to adding a couple of lines above the above
819 mockup, assuming default keybindings:
821 (S) server: gonzales.homelinux.org:27001  [...]  (C) cache only     (T) tutorial
822 (L) lock: plug2              (e) edit   (s) set   (n/p) next/prev  (R) rename
823                                       ZGZ
824                                   (R) register
827 IMConfirm should be removed, becoming a special cross-IM case of prompting. In
828 both curses and SDL UIs, this is handled with a prompt line at the bottom.
830 Lock library: just a directory within the confdir containing lockfiles. Should
831 be able to enter any path, relative or absolute, with relative paths
832 interpreted as relative to the default lock dir and with mkdirhier applied as
833 appropriate. All locks stored with ppshow, so revision control systems etc
834 won't be useless. Locks shown in order of modification. Tab completion up to
835 longest unique stem, and then cycling through completions.
837 Undeclared notes: need to clear out notes when they become undeclarable
840 Terminology:
841     Locks are placed, then solved, then accessed.
842     Notes are taken on a lock; declared; secured behind a lock; read.