From 4064156a2255f78efa4f7d5b71b32068f776c9b0 Mon Sep 17 00:00:00 2001 From: rolevax Date: Sat, 30 Jun 2018 18:34:46 +0800 Subject: [PATCH] move doc index to home page --- Gemfile.lock | 149 +++++++++--------- _config.yml | 3 - _data/abbr.yml | 132 ++++++++++++++++ _data/lua-api.yml | 213 ++++++++++++++++++++++--- _data/lua-callbacks.yml | 53 +++++++ bugging.md | 8 +- contribute.md | 3 +- docs/abbr.md | 27 ++++ docs/cpp-note.md | 6 +- docs/cpp.md | 2 +- docs/dev-setup.md | 98 +++++++----- docs/editor/api.md | 108 ++++++++----- docs/editor/flow.md | 190 +++++++++++++++++++++++ docs/editor/func.md | 238 ++++++++++++++++++++++++++-- docs/editor/local.md | 335 ++++++++++++++++++++++++++++++++++++++++ docs/editor/start.md | 14 +- docs/editor/userdata.md | 208 +++++++++++++++++++++++++ docs/editor/var.md | 5 +- docs/girl.md | 47 +++--- docs/libsaki/mount.md | 2 +- docs/phil.md | 3 +- docs/rule.md | 8 +- docs/start.md | 37 ++--- feedback.md | 2 - index.md | 106 +++++++++---- signup-pass.md | 2 +- signup.md | 4 +- 27 files changed, 1711 insertions(+), 292 deletions(-) create mode 100644 _data/abbr.yml create mode 100644 _data/lua-callbacks.yml create mode 100644 docs/abbr.md create mode 100644 docs/editor/flow.md create mode 100644 docs/editor/local.md create mode 100644 docs/editor/userdata.md diff --git a/Gemfile.lock b/Gemfile.lock index 0a48f64..d6874aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - activesupport (4.2.9) + activesupport (4.2.10) i18n (~> 0.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) @@ -13,90 +13,99 @@ GEM execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.17.9) + commonmarker (0.17.11) ruby-enum (~> 0.5) concurrent-ruby (1.0.5) + dnsruby (1.61.2) + addressable (~> 2.5) + em-websocket (0.5.1) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.6.0) ethon (0.11.0) ffi (>= 1.3.0) + eventmachine (1.2.7) execjs (2.7.0) - faraday (0.14.0) + faraday (0.15.2) multipart-post (>= 1.2, < 3) - ffi (1.9.23) + ffi (1.9.25) forwardable-extended (2.6.0) gemoji (3.0.0) - github-pages (179) - activesupport (= 4.2.9) - github-pages-health-check (= 1.4.0) - jekyll (= 3.6.2) - jekyll-avatar (= 0.5.0) + github-pages (191) + activesupport (= 4.2.10) + github-pages-health-check (= 1.8.1) + jekyll (= 3.7.3) + jekyll-avatar (= 0.6.0) jekyll-coffeescript (= 1.1.1) jekyll-commonmark-ghpages (= 0.1.5) jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.9.3) + jekyll-feed (= 0.10.0) jekyll-gist (= 1.5.0) jekyll-github-metadata (= 2.9.4) - jekyll-mentions (= 1.3.0) + jekyll-mentions (= 1.4.1) jekyll-optional-front-matter (= 0.3.0) jekyll-paginate (= 1.1.0) jekyll-readme-index (= 0.2.0) - jekyll-redirect-from (= 0.13.0) + jekyll-redirect-from (= 0.14.0) jekyll-relative-links (= 0.5.3) - jekyll-remote-theme (= 0.2.3) + jekyll-remote-theme (= 0.3.1) jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.4.0) + jekyll-seo-tag (= 2.5.0) jekyll-sitemap (= 1.2.0) jekyll-swiss (= 0.4.0) - jekyll-theme-architect (= 0.1.0) - jekyll-theme-cayman (= 0.1.0) - jekyll-theme-dinky (= 0.1.0) - jekyll-theme-hacker (= 0.1.0) - jekyll-theme-leap-day (= 0.1.0) - jekyll-theme-merlot (= 0.1.0) - jekyll-theme-midnight (= 0.1.0) - jekyll-theme-minimal (= 0.1.0) - jekyll-theme-modernist (= 0.1.0) - jekyll-theme-primer (= 0.5.2) - jekyll-theme-slate (= 0.1.0) - jekyll-theme-tactile (= 0.1.0) - jekyll-theme-time-machine (= 0.1.0) + jekyll-theme-architect (= 0.1.1) + jekyll-theme-cayman (= 0.1.1) + jekyll-theme-dinky (= 0.1.1) + jekyll-theme-hacker (= 0.1.1) + jekyll-theme-leap-day (= 0.1.1) + jekyll-theme-merlot (= 0.1.1) + jekyll-theme-midnight (= 0.1.1) + jekyll-theme-minimal (= 0.1.1) + jekyll-theme-modernist (= 0.1.1) + jekyll-theme-primer (= 0.5.3) + jekyll-theme-slate (= 0.1.1) + jekyll-theme-tactile (= 0.1.1) + jekyll-theme-time-machine (= 0.1.1) jekyll-titles-from-headings (= 0.5.1) - jemoji (= 0.9.0) - kramdown (= 1.16.2) + jemoji (= 0.10.1) + kramdown (= 1.17.0) liquid (= 4.0.0) listen (= 3.1.5) mercenary (~> 0.3) - minima (= 2.4.0) - nokogiri (>= 1.8.1, < 2.0) + minima (= 2.5.0) + nokogiri (>= 1.8.2, < 2.0) rouge (= 2.2.1) terminal-table (~> 1.4) - github-pages-health-check (1.4.0) + github-pages-health-check (1.8.1) addressable (~> 2.3) - net-dns (~> 0.8) + dnsruby (~> 1.60) octokit (~> 4.0) public_suffix (~> 2.0) typhoeus (~> 1.3) - html-pipeline (2.7.1) + html-pipeline (2.8.4) activesupport (>= 2) nokogiri (>= 1.4) + http_parser.rb (0.6.0) i18n (0.9.5) concurrent-ruby (~> 1.0) - jekyll (3.6.2) + jekyll (3.7.3) addressable (~> 2.4) colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 0.7) jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 1.1) + jekyll-watch (~> 2.0) kramdown (~> 1.14) liquid (~> 4.0) mercenary (~> 0.3.3) pathutil (~> 0.9) - rouge (>= 1.7, < 3) + rouge (>= 1.7, < 4) safe_yaml (~> 1.0) - jekyll-avatar (0.5.0) + jekyll-avatar (0.6.0) jekyll (~> 3.0) jekyll-coffeescript (1.1.1) coffee-script (~> 2.2) coffee-script-source (~> 1.11.1) - jekyll-commonmark (1.1.0) + jekyll-commonmark (1.2.0) commonmarker (~> 0.14) jekyll (>= 3.0, < 4.0) jekyll-commonmark-ghpages (0.1.5) @@ -105,15 +114,14 @@ GEM rouge (~> 2) jekyll-default-layout (0.1.4) jekyll (~> 3.0) - jekyll-feed (0.9.3) + jekyll-feed (0.10.0) jekyll (~> 3.3) jekyll-gist (1.5.0) octokit (~> 4.2) jekyll-github-metadata (2.9.4) jekyll (~> 3.1) octokit (~> 4.0, != 4.4.0) - jekyll-mentions (1.3.0) - activesupport (~> 4.0) + jekyll-mentions (1.4.1) html-pipeline (~> 2.3) jekyll (~> 3.0) jekyll-optional-front-matter (0.3.0) @@ -121,71 +129,69 @@ GEM jekyll-paginate (1.1.0) jekyll-readme-index (0.2.0) jekyll (~> 3.0) - jekyll-redirect-from (0.13.0) + jekyll-redirect-from (0.14.0) jekyll (~> 3.3) jekyll-relative-links (0.5.3) jekyll (~> 3.3) - jekyll-remote-theme (0.2.3) + jekyll-remote-theme (0.3.1) jekyll (~> 3.5) rubyzip (>= 1.2.1, < 3.0) - typhoeus (>= 0.7, < 2.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.4.0) + jekyll-seo-tag (2.5.0) jekyll (~> 3.3) jekyll-sitemap (1.2.0) jekyll (~> 3.3) jekyll-swiss (0.4.0) - jekyll-theme-architect (0.1.0) + jekyll-theme-architect (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-cayman (0.1.0) + jekyll-theme-cayman (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-dinky (0.1.0) + jekyll-theme-dinky (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-hacker (0.1.0) + jekyll-theme-hacker (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-leap-day (0.1.0) + jekyll-theme-leap-day (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-merlot (0.1.0) + jekyll-theme-merlot (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-midnight (0.1.0) + jekyll-theme-midnight (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-minimal (0.1.0) + jekyll-theme-minimal (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-modernist (0.1.0) + jekyll-theme-modernist (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-primer (0.5.2) + jekyll-theme-primer (0.5.3) jekyll (~> 3.5) jekyll-github-metadata (~> 2.9) - jekyll-seo-tag (~> 2.2) - jekyll-theme-slate (0.1.0) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-tactile (0.1.0) + jekyll-theme-tactile (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) - jekyll-theme-time-machine (0.1.0) + jekyll-theme-time-machine (0.1.1) jekyll (~> 3.5) jekyll-seo-tag (~> 2.0) jekyll-titles-from-headings (0.5.1) jekyll (~> 3.3) - jekyll-watch (1.5.1) + jekyll-watch (2.0.0) listen (~> 3.0) - jemoji (0.9.0) - activesupport (~> 4.0, >= 4.2.9) + jemoji (0.10.1) gemoji (~> 3.0) html-pipeline (~> 2.2) jekyll (~> 3.0) - kramdown (1.16.2) + kramdown (1.17.0) libv8 (3.16.14.19) liquid (4.0.0) listen (3.1.5) @@ -194,16 +200,15 @@ GEM ruby_dep (~> 1.2) mercenary (0.3.6) mini_portile2 (2.3.0) - minima (2.4.0) + minima (2.5.0) jekyll (~> 3.5) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.11.3) multipart-post (2.0.0) - net-dns (0.8.0) - nokogiri (1.8.2) + nokogiri (1.8.4) mini_portile2 (~> 2.3.0) - octokit (4.8.0) + octokit (4.10.0) sawyer (~> 0.8.0, >= 0.5.3) pathutil (0.16.1) forwardable-extended (~> 2.6) @@ -218,7 +223,7 @@ GEM ruby_dep (1.5.0) rubyzip (1.2.1) safe_yaml (1.0.4) - sass (3.5.5) + sass (3.5.7) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -236,7 +241,7 @@ GEM ethon (>= 0.9.0) tzinfo (1.2.5) thread_safe (~> 0.1) - unicode-display_width (1.3.0) + unicode-display_width (1.4.0) PLATFORMS ruby @@ -249,7 +254,7 @@ DEPENDENCIES tzinfo-data RUBY VERSION - ruby 2.5.0p0 + ruby 2.5.1p57 BUNDLED WITH - 1.16.1 + 1.16.4 diff --git a/_config.yml b/_config.yml index b52513b..0cb02c0 100644 --- a/_config.yml +++ b/_config.yml @@ -7,10 +7,7 @@ baseurl: "" url: "" github_username: rolevax header_pages: - - docs.md - feedback.md - - contribute.md - - crowd.md webrick: headers: Access-Control-Allow-Origin: "*" diff --git a/_data/abbr.yml b/_data/abbr.yml new file mode 100644 index 0000000..396a2e2 --- /dev/null +++ b/_data/abbr.yml @@ -0,0 +1,132 @@ +- + abbr: ct + full: count + desc: 计数、个数 +- + abbr: num + full: number + desc: 个数、号码 +- + abbr: s11n + full: serialization +- + abbr: i18n + full: internationalization +- + abbr: impl + full: implementation +- + abbr: pimpl + full: pointer to implementation +- + abbr: ptr + full: pointer +- + abbr: ref + full: reference +- + abbr: res + full: result +- + abbr: iff + full: if and only if +- + abbr: str + full: string +- + abbr: err + full: error +- + abbr: expr + full: expression +- + abbr: stmt + full: statement +- + abbr: cmd + full: command +- + abbr: msg + full: message +- + abbr: regex + full: regular expression +- + abbr: uid + full: user ID +- + abbr: func + full: function +- + abbr: dir + full: directory +- + abbr: tan90 + full: does not exist +- + abbr: iter + full: iterator, iteration +- + abbr: val + full: value +- + abbr: var + full: variable +- + abbr: prev + full: previous +- + abbr: indic + full: indicator +- + abbr: perm + full: permutation +- + abbr: seq + full: sequence +- + abbr: inc + full: increase +- + abbr: eff + full: effect, effective +- + abbr: arg + full: argument +- + abbr: param + full: parameter +- + abbr: init + full: initialize +- + abbr: ctrl + full: control, controller +- + abbr: ctx + full: context +- + abbr: cp + full: chii or pon +- + abbr: dmk + full: daiminkan +- + abbr: cpdmk + full: chii, pon, or daiminkan +- + abbr: irs + full: in-round skill +- + abbr: ors + full: out-of-round skill +- + abbr: drid + full: dora indicator +- + abbr: urid + full: uradora indicator +- + abbr: desc + full: description + diff --git a/_data/lua-api.yml b/_data/lua-api.yml index 34162a1..37e3488 100644 --- a/_data/lua-api.yml +++ b/_data/lua-api.yml @@ -3,23 +3,18 @@ members: - name: "构造1" - syntax: "`T34.new(Suit.M, 5)`" - params: - - "`Suit`" - - number - returns: - - "`T34`" - desc: 通过花色与数值创建。 - - - name: "构造2" syntax: '`T34.new("5m")`' params: - string returns: - "`T34`" - desc: 通过字符串创建。 + desc: + 通过字符串创建。
+ 第一个字符代表数值,第二个字符代表花色。
+ `"1m"`, `"2p"`, `"3s"`代表 1 万、2 饼、3 索;
+ `"1f"`, `"2f"`, `"3f"`, `"4f"`, `"1y"`, `"2y"`, `"3y"`分别代表东南西北白发中。 - - name: "构造3" + name: "构造2" syntax: "`T34.new(4)`" params: - number @@ -33,6 +28,34 @@ returns: - number desc: 获取 ID-34。 + - + name: "`suit`" + syntax: "`t:suit()`" + params: + returns: + - string + desc: + 获取花色。
+ `"m"`, `"p"`, `"s"`, `"f"`, `"y"`分别表示万、饼、索、风牌、三元牌。 + - + name: "`val`" + syntax: "`t:val()`" + params: + returns: + - number + desc: + 获取数值。
+ 数牌返回 1~9; + 风牌通过 1, 2, 3, 4 分别表示东南西北; + 三元牌通过 1, 2, 3 分别表示白发中。 + - + name: "`str34`" + syntax: "`t:str34()`" + params: + returns: + - string + desc: + 获取对应的字符串。 - name: "`isyakuhai`" syntax: "`t:isyakuhai(sw, rw)`" @@ -50,10 +73,53 @@ - "`T34`" returns: - boolean - desc: "判断两张牌是否相等,无视赤黑。" + desc: "判断两张牌是否相等。同花色的赤 5 和黑 5 也是相等的。" - name: "static `all`" syntax: "`ipairs(T34.all)`" desc: 遍历全部 34 种牌。 +- + name: T37 + members: + - + name: "构造1" + syntax: '`T37.new("0m")`' + params: + - string + returns: + - "`T37`" + desc: + 通过字符串创建。
+ 可通过`"0m"`, `"0p"`, `"0s"`创建赤宝牌,其余同`T34`。 + - + name: "构造2" + syntax: "`T37.new(4)`" + params: + - number + returns: + - "`T37`" + desc: 通过 ID-34 创建。此方法不创建赤牌。 + - + name: 继承的方法 + syntax: "`t.suit()`, `t.val()`, ..." + params: + returns: + desc: "`T34`的方法也可以用在`T37`上。" + - + name: "`isaka5`" + syntax: "`t:isaka5()`" + params: + returns: + - string + desc: + 判断是否为赤 5。 + - + name: "`str37`" + syntax: "`t:str37()`" + params: + returns: + - string + desc: + 获取对应的字符串,以`"0m"`, `"0p"`, `"0s"`表示赤 5。 - name: Who members: @@ -95,11 +161,10 @@ syntax: "`meld:type()`" params: returns: - - "`M37.Type`" + - string desc: - 获取 meld 类型。 - 返回值为`M37.Type.CHII`, `M37.Type.PON`, `M37.Type.DAIMINKAN`, - `M37.Type.ANKAN`, `M37.Type.KAKAN`中的一个。 + 获取 meld 类型。返回值为 + `"chii"`, `"pon"`, `"daiminkan"`,`"ankan"`, `"kakan"`中的一个。 - name: "`[]`" syntax: "`meld[2]`" @@ -113,6 +178,50 @@ - name: Mount members: + - + name: "`remainpii`" + syntax: "`mount:remainpii()`" + params: + returns: + - number + desc: 查看壁牌残杖 + - + name: "`remainrinshan`" + syntax: "`mount:remainrinshan()`" + params: + returns: + - number + desc: 查看岭上牌残杖 + - + name: "`remaina`1" + syntax: "`mount:remaina(tile)`" + params: + - "`T34`" + returns: + - number + desc: 查看 A 区中`tile`的残杖 + - + name: "`remaina`2" + syntax: "`mount:remaina(tile)`" + params: + - "`T37`" + returns: + - number + desc: 同上,以`T37`为参数,赤牌敏感 + - + name: "`getdrids`" + syntax: "`mount:getdrids()`" + params: + returns: + - 某类似数组的`T37`容器 + desc: 读取已翻出的(杠)宝牌指示牌序列 + - + name: "`geturids`" + syntax: "`mount:geturids()`" + params: + returns: + - 某类似数组的`T37`容器 + desc: 读取(立直和牌后)已亮出的(杠)里宝牌指示牌序列 - name: "`lighta`1" syntax: "`mount:lighta(tile, mk)`" @@ -130,6 +239,50 @@ - boolean returns: desc: 同上,多一个指定是否为岭上出口的参数。 + - + name: "`lightb`1" + syntax: "`mount:lightb(tile, mk)`" + params: + - "`T34`" + - number + returns: + desc: 以`mk`增加 B 区中`tile`的存在感。 + - + name: "`lightb`2" + syntax: "`mount:lightb(tile, mk, rinshan)`" + params: + - "`T34`" + - number + - boolean + returns: + desc: 同上,多一个指定是否为岭上出口的参数。 + - + name: "`incmk`1" + syntax: "`mount:incmk(exit, pos, tile, mk, bspace)`" + params: + - string + - number + - "`T34`" + - number + - boolean + returns: + desc: + 以`mk`增加出口`exit`之`pos`处`tile`的存在感。
+ `exit`需传入`"pii"`, `"rinshan"`, `"dorahyou"`, `"urahyou"`之一, + 分别代表普通壁牌、岭上牌、未翻开的表宝牌指示牌、未挖出的里宝牌指示牌。
+ `pos`为 0 时代表出口处队首牌,1 时代表队首的下一张牌,以此类推。
+ `bspace`为`true`时干涉 B 区,否则干涉 A 区。 + - + name: "`incmk`2" + syntax: "`mount:incmk(exit, pos, tile, mk, bspace)`" + params: + - string + - number + - "`T37`" + - number + - boolean + returns: + desc: "`incmk`的赤牌敏感版,以`T37`为参数,其余同上" - name: Tilecount members: @@ -143,9 +296,9 @@ desc: 获取集合中`tile`的数量。 - name: "`ct`2" - syntax: "`tc:ct(Suit.M)`" + syntax: '`tc:ct("m")`' params: - - "`Suit`" + - string(详见`T34`的`suit`方法) returns: - number desc: 获取集合中某一花色牌的数量。 @@ -174,6 +327,13 @@ returns: - number desc: 计算某种牌的数量,含副露。 + - + name: "`ctaka5`" + syntax: "`hand:ctaka5()`" + params: + returns: + - number + desc: 计算赤 5 的数量,含副露。 - name: "`ready`" syntax: "`hand:ready()`" @@ -230,6 +390,14 @@ returns: - boolean desc: 判断是否为门前清。 + - + name: "`%`" + syntax: "`indicators % hand`, `tile % hand`" + params: + - "`mount:drids`或`mount:urids`的返回值,或`T34`" + returns: + - number + desc: 计算宝牌个数。 - name: Game members: @@ -274,7 +442,14 @@ name: "`getroundwind`" syntax: "`game:getroundwind()`" params: - - "`Who`" returns: - number desc: 获取本局场风数值(1 ~ 4 分别表示东南西北)。 + - + name: "`getriver`" + syntax: "`game:getriver(who)`" + params: + - "`Who`" + returns: + - "某类似数组的`T34`容器" + desc: 获取某家牌河。 diff --git a/_data/lua-callbacks.yml b/_data/lua-callbacks.yml new file mode 100644 index 0000000..608d75a --- /dev/null +++ b/_data/lua-callbacks.yml @@ -0,0 +1,53 @@ +- + name: checkinit + desc: + 检查配牌,当且仅当满意配牌时返回`true` + params: + - + name: game + type: userdata `Game` + desc: 当前牌桌数据 + - + name: init + type: userdata `Hand` + desc: 待测配牌,无论亲子都是 13 张 + - + name: who + type: userdata `Who` + desc: 待测配牌所有者 + - + name: iter + type: number + desc: 检测轮数,从0 开始递增,最大 999 +- + name: ondraw + desc: 摸牌前被调用,可干涉牌山 + params: + - + name: game + type: userdata `Game` + desc: 当前牌桌数据 + - + name: mount + type: userdata `Mount` + desc: 牌山 + - + name: who + type: userdata `Who` + desc: 将要摸牌的人 + - + name: rinshan + type: boolean + desc: 下一张摸牌是否为岭上牌 +- + name: ongameevent + desc: 发生某些事件前调用,不可直接干涉牌山 + params: + - + name: game + type: userdata `Game` + desc: 当前牌桌数据 + - + name: event + type: table + desc: 发生的事件 diff --git a/bugging.md b/bugging.md index f7fabf7..cc99a18 100644 --- a/bugging.md +++ b/bugging.md @@ -6,13 +6,11 @@ permalink: /bugging/ 「骚扰」指反馈、众包任务过程中, 贡献者做出的极端烦人行为。 -本条例主要针对神经病设立, -正常人不必过于担心骚扰判定问题。 +本条例默认不公开,只会针对性地出示给有必要警告的贡献者。 贡献者做出骚扰行为时,会被扣除一定的贡献度。 多数情况下,首次骚扰扣除 1000 点,往后则翻倍增加扣除额度。 - 下文详细定义了骚扰行为的判定标准。 1. 无知有理 - A 类 @@ -43,9 +41,9 @@ permalink: /bugging/ 反馈者发布大量(刷屏级)无法获得贡献度的反馈时, 适用「垃圾反馈泛滥」判定。 若不具备自行鉴别垃圾反馈的能力,则应学会闭嘴。 -7. 催促验收 +7. 急太监 贡献者在众包平台上点击「通知验收」后,无需再通过其它途径另行通知验收。 - 通过其它途径通知验收、或询问验收时间,则「催促验收」判定成立。 + 通过其它途径通知验收、或询问验收时间,则「急太监」判定成立。 8. 轻视审查 贡献者所提交的代码中反复犯同样的错误时, 「轻视审查」判定成立。 diff --git a/contribute.md b/contribute.md index 5f38f17..d5a14cd 100644 --- a/contribute.md +++ b/contribute.md @@ -30,7 +30,8 @@ permalink: /contribute/ 获得「贡献度」。 贡献度大于 0 的 ID 会出现在 app 封面上。 -同时,贡献度是零食的领取基准,每周领取零食量 = 50 x 贡献度。 + +[注册松饼社区 ID](/signup/) diff --git a/docs/abbr.md b/docs/abbr.md new file mode 100644 index 0000000..3c5f6fc --- /dev/null +++ b/docs/abbr.md @@ -0,0 +1,27 @@ +--- +layout: page +title: 已认证常见缩写 +permalink: /docs/abbr/ +--- + +下表中包括的都是可以在代码中随意使用的缩写。 +不包括的就不一定了,有可能能用也有可能不能用。 + +建议使用「Ctrl + F」搜索。 + + + + + + + +{% assign sorted-abbr = site.data.abbr | sort: 'abbr' %} +{% for abbr in sorted-abbr %} + + + + + +{% endfor %} +
缩写全称解释
{{ abbr.abbr }}{{ abbr.full }}{{ abbr.desc | markdownify }}
+ diff --git a/docs/cpp-note.md b/docs/cpp-note.md index 196e100..3d0e9a0 100644 --- a/docs/cpp-note.md +++ b/docs/cpp-note.md @@ -8,9 +8,9 @@ permalink: /docs/cpp-note/ 返回[松饼 C++ 代码规范](/docs/cpp/)页面 -## 对”简单阶梯形“与”简单锯齿形“的定义 +## 对「简单阶梯形」与「简单锯齿形」的定义 -“简单阶梯形”的基本定义:缩进层级逐行加一。 +「简单阶梯形」的基本定义:缩进层级逐行加一。 ``` // 简单阶梯形 @@ -37,7 +37,7 @@ while (hungry()) { - 条件必须只占一行。只要条件占据多行,就不是简单阶梯形。 - 带有`else`的`if`不属于简单阶梯形。 -“简单锯齿形”的基本定义:缩进层级逐行交替增减的`if`语句。 +「简单锯齿形」的基本定义:缩进层级逐行交替增减的`if`语句。 ``` // 简单锯齿形 diff --git a/docs/cpp.md b/docs/cpp.md index d2ed2a8..0075040 100644 --- a/docs/cpp.md +++ b/docs/cpp.md @@ -40,7 +40,7 @@ permalink: /docs/cpp/ - 要:`Http`(大驼峰),`http`(小驼峰) - [NM-6] 用小写字母或数字为 namespace 命名。 - [NM-7] 用大写字母和下划线为枚举值和常量命名。 -- [NM-8] 鼓励使用短命名与常见的缩写。 +- [NM-8] 鼓励使用短命名与[常见的缩写](/docs/abbr/)。 - [NM-9] 命名需带有自解释性,禁止使用无意义命名。 - 好:`Dog odie;` - 可以:`Dog d;`(`d`可看作`Dog`的缩写) diff --git a/docs/dev-setup.md b/docs/dev-setup.md index b81a9d0..ee89227 100644 --- a/docs/dev-setup.md +++ b/docs/dev-setup.md @@ -4,71 +4,97 @@ title: 搭建开发环境 permalink: /docs/dev-setup/ --- -## 概述 +## 索引 -所有的松饼项目都可以在 Linux, Windows, macOS 上开发。 +根据使用的平台和开发的目标选读: -如果没啥特殊情况,强烈建议按照以下流程搭建环境。 -我们的开发环境对现有系统应该没有污染性。 -不按照以下步骤搭环境的,我们无法予以帮助。 +- [在 Linux 上开发`libsaki`或`mjpancake`](#linux-client) +- [在 Windows 上开发`libsaki`或`mjpancake`](#windows-client) +- [在 macOS 上开发`libsaki`或`mjpancake`](#macos-client) +- [开发 Android 客户端](#android) +- [开发`ih`](#ih) -
+{% capture client-cond %} +理论上,只要满足以下所有条件,就可以进行开发: -## 客户端或核心库的环境搭建 +- 有一个完整支持 C++17 的编译器 +- 装有最新版 Qt +{% endcapture %} -1. 根据平台不同,安装一些必要的东西 - - Windows:安装 [mingw-w64][mingw-w64]{:target="_blank"} - - 安装路径不能带空格 - - 安装时选择「最新版, i686, posix, dwarf」 - - macOS:通过 AppStore 安装最新版 Xcode - - Linux:GCC/G++ 7.x 或以上 -2. 下载并安装 Qt 5.10.1 开源版 +{% capture install-qt %} +1. 下载并安装 Qt 5.11.1 开源版 - 下载地址:[镜像][qt-mirror]{:target="_blank"} 或 [官网][qt]{:target="_blank"} - - 大陆网络环境下推荐使用镜像 - - Windows 安装时勾选 MinGW 组件 - - Windows 安装 Qt 后需要额外的配置,见下面的 [关于Windows构建](#winbuild) -3. 从`mjpancake`和`libsaki`创建fork (为将来方便,两个都fork) - - 进入[`mjpancake`][mjpancake]{:target="_blank"}页面,点右上角的fork - - 进入[`libsaki`][libsaki]{:target="_blank"}页面,点右上角的fork -4. 通过以下命令克隆仓库并配置`upstream`远端:(替换掉`your-username`) + - 大陆网络环境下推荐使用镜像 +{% endcapture %} + +{% capture create-fork %} +1. 从 [`mjpancake`][mjpancake]{:target="_blank"} + 以及 [`libsaki`][libsaki]{:target="_blank"} 创建 fork + - 同时可通过加 star 方便将来访问 +1. 通过以下命令克隆仓库并配置`upstream`远端:(替换掉`your-username`) - `git clone --recursive https://github.com/your-username/mjpancake.git` - `cd mjpancake` - `git remote add upstream https://github.com/rolevax/mjpancake.git` - `cd libsaki` - `git remote rename origin upstream` - `git remote add origin https://github.com/your-username/libsaki.git` + - 在以后的交流中,我们会假定`origin`指代 fork 出的仓库, + `upstream`指代松饼的官方仓库。 +{% endcapture %} -在以后的交流中,我们会假定`origin`与`upstream`都是用上述命令配出来的。 - +{% capture client-end %} 环境搭建好以后, 用 Qt Creator 打开代码目录下的`mjpancake.pro`项目, -点击左下角的Build按钮进行编译。 +点击左下角的 Build 按钮进行编译。 编译成功通过则说明环境搭建完成。 +首次编译时可能会报出有关 QML 的语法错误, +此系静态分析器的问题所致,不影响程序的运行时行为,可无视。 + `libsaki`和`mjpancake`之间不存在必须同步更新的关系。 众包平台上的任务通常只需要修改`mjpancake`和`libsaki`中的一个, 不会出现两者都需要提交的情况。 首次接触`libsaki`代码的, 建议阅读[Libsaki代码导读](/docs/libsaki/),快速了解整体设计。 +{% endcapture %} + +## 在 Linux 上开发 libsaki 或 mjpancake + +{{ client-cond }} + +具体步骤: -
+1. 安装 7.x 或以上的 G++{{ install-qt }}{{ create-fork }}{{ client-end }} -## 关于 Windows 构建 -Qt 自带的 mingw 编不过 Libsaki, -我们的解决方案是使用 mingw-w64。 -(mingw 和 mingw-w64 是两家东西) +## 在 Windows 上开发 libsaki 或 mjpancake -打开 Qt Creator,「工具」->「选项」, -将 C 与 C++ 的编译器都改成 mingw-w64 的,如下图。 +{{ client-cond }} + +具体步骤: + +1. 安装 [mingw-w64][mingw-w64]{:target="_blank"} + + - 安装路径不能带空格 + - 安装时选择「最新版, i686, posix, dwarf」 +{{ install-qt }} - 安装时勾选 MinGW 组件 +{{ create-fork }} +1. 打开 Qt Creator,「工具」->「选项」, + 将 C 与 C++ 的编译器都改成 mingw-w64 的,如下图。 ![配置mingw-w64]({{ "/assets/mingw.png" | absolute_url }}) -
+{{ client-end }} + +## 在 macOS 上开发 libsaki 或 mjpancake -## 关于 Android 客户端 +1. 通过 AppStore 安装最新版 Xcode{{ install-qt }} +{{ create-fork }} +{{ client-end }} + +## 开发 Android 客户端 Qt 官方建议使用 Android NDK r10e, 然而 r10e 自带的 G++ 编不过 Libsaki。 @@ -80,9 +106,7 @@ Qt 官方建议使用 Android NDK r10e, 3. 通过 NDK 里的 Clang 编译 Qt(需要几个小时) 4. 通过这个新编译出的 Qt 构建`mjpancake.pro` -
- -## 服务器开发环境搭建 +## 开发 ih `ih`的开发环境和运行环境都被做成了 Docker 镜像, 因此需要安装的东西只有 Docker 和 Docker Compose。 @@ -108,7 +132,7 @@ Qt 官方建议使用 Android NDK r10e, [mingw-w64]: https://mingw-w64.org/doku.php/download/mingw-builds [git-win]: https://git-for-windows.github.io/ [qt]: https://www.qt.io -[qt-mirror]: http://mirrors.ustc.edu.cn/qtproject/archive/qt/5.10/5.10.1/ +[qt-mirror]: http://mirrors.ustc.edu.cn/qtproject/archive/qt/5.11/5.11.1/ [docker]: https://docs.docker.com/engine/installation/ [docker-compose]: https://docs.docker.com/compose/install/ diff --git a/docs/editor/api.md b/docs/editor/api.md index a514479..b32cb93 100644 --- a/docs/editor/api.md +++ b/docs/editor/api.md @@ -7,7 +7,15 @@ permalink: /docs/editor/api/ 本页包含松饼人物编辑器目前为止的全部接口。 推荐使用「Ctrl + F」进行查找。 -## 回调函数 +## 索引 + +- [回调函数](#callback) +- [可用的 Lua 标准库与内建函数](#std) +- [各 userdata 接口](#userdata) +- [Game Event 表结构](#event) +- [与 C++ 接口的关系](#cpp) + +## 回调函数 在顶级 chunck 中以特定的名字定义函数, 即可在对应时刻执行指定的逻辑。 @@ -15,36 +23,44 @@ permalink: /docs/editor/api/ 这些函数都不需要参数, 必要的数据可从特定的全局变量中获取。 -|-------|--------|--------| -|函数名|调用时机|可用全局变量| -|-------|--------|--------| -|`ondraw`|摸牌之前|`game`, `mount`, `who`, `rinshan` | -|-------|--------|--------| - -## 全局变量 - -为了免除在写回调时记忆参数顺序的麻烦, -我们使用名字固定的全局变量提供必要的数据。 -可以把这些全局变量的名字当成关键字看待。 - -在一个回调函数的内部, -并非所有的全局变量都是可用的。 -上面的「回调函数」表中列举了在哪些回调中可使用哪些全局变量。 - -|-------|--------|--------| -|变量名 |类型|简介| -|--------|--------|--------| -|`game`|userdata `Game`|当前牌桌数据| -|`mount`|userdata `Mount`|牌山| -|`who`|userdata `Who`|事件关系人| -|`rinshan`|boolean|下一张摸牌是否为岭上牌| -|`self`|userdata `Who`|本角色,在所有回调中可用| -|--------|--------|--------| + + + + + +{% for cb in site.data.lua-callbacks %} + + + + + + + +{% endfor %} +
函数名作用
{{ cb.name }}{{ cb.desc | markdownify | remove: "

" | remove: "

" }}
+ 可用全局变量: +
    +{% for param in cb.params %} +
  • {{ param.name }} +
      +
    • 类型:{{ param.type | markdownify | remove: "

      " | remove: "

      " }}
    • +
    • {{ param.desc | markdownify | remove: "

      " | remove: "

      " }}
    • +
    +
  • +{% endfor %} +
  • self +
      +
    • 类型:userdata Who
    • +
    • 本角色
    • +
    +
  • +
+
-## 可用的 Lua 标准库与内建函数 +## 可用的 Lua 标准库与内建函数 -为了防止世界被破坏,为了维护世界的和平, -松饼中能用的 Lua 标准库与内建函数是原版 Lua 的一个子集。 +为了防止世界被破坏, +松饼中只能使用一部分的 Lua 标准库与内建函数。 能用的部分: @@ -53,10 +69,11 @@ permalink: /docs/editor/api/ - `math`中除去`math.random`和`math.randomseed`以外的所有函数 - `pairs`, `ipairs` - `print` +- `tostring` 将来可能会放宽限制,支持更多的标准库成员。 -## 各 userdata 接口 +## 各 userdata 接口 {% for class in site.data.lua-api %}

{{ class.name }}

@@ -67,8 +84,8 @@ permalink: /docs/editor/api/ {% for member in class.members %} - {{ member.name | markdownify }} - {{ member.syntax | markdownify }} + {{ member.name | markdownify|remove:"

"|remove:"

" }} + {{ member.syntax | markdownify|remove:"

"|remove:"

" }} 参数类型 @@ -76,7 +93,7 @@ permalink: /docs/editor/api/ {% assign ps = member.params[0] %} {% assign tail = member.params | shift %} {% for p in tail %}{% assign ps = ps | append: ", " | append: p %}{% endfor %} - {{ ps | markdownify }} + {{ ps | markdownify | remove: "

" | remove: "

" }} @@ -85,13 +102,34 @@ permalink: /docs/editor/api/ {% assign rs = member.returns[0] %} {% assign tail = member.returns | shift %} {% for r in tail %}{% assign rs = rs | append: ", " | append: r %}{% endfor %} - {{ rs | markdownify }} + {{ rs | markdownify | remove: "

" | remove: "

" }} - {{ member.desc | markdownify }} + + {{ member.desc | markdownify | remove: "

" | remove: "

" }} + {% endfor %} {% endfor %} +## Game Event 表结构 + +`ongameevent`中使用的`event`变量类型为 table, +包含`type`和`args`两个字段。 +`type`字段为 string 类型,表示事件的类别; +`args`字段为 table 类型,根据`type`的不同含有不同的字段。 + +(文档准备中。目前可通过自行`pairs`遍历查看`args`内容。) + +## 与 C++ 接口的关系 + +松饼的 Lua 接口与 C++ 接口之间存在以下关联与区别: + +- C++ 里的`Table`在 Lua 中一律改称`Game` +- C++ 接口基于驼峰命名,Lua 的命名方式参照标准库,全小写且无分隔 + (userdata 类名首字母大写) +- C++ 以 assert 或 UB 处理傻逼逻辑,Lua 则会报运行时错误 + (Lua 代码导致松饼主程序崩溃的情况属于 bug) + diff --git a/docs/editor/flow.md b/docs/editor/flow.md new file mode 100644 index 0000000..45c1a15 --- /dev/null +++ b/docs/editor/flow.md @@ -0,0 +1,190 @@ +--- +layout: page +title: 控制流 +permalink: /docs/editor/flow/ +--- + +「松饼人物编辑器:从入门到欧耶」系列教程(六) + +## 上一讲的习题参考答案 + +
+ +## 多级 if 嵌套 + +回顾一下第一讲中,自己摸牌输出「哇!」, +别人摸牌输出「emmm...」的那个例子: + +```lua +function ondraw() + if who == self then + print("哇!") + else + print("emmm...") + end +end +``` + +现在我们把这个例子扩展一下, +让它在下家摸牌的输出「鄙视下家」,其余的不变: + +```lua +function ondraw() + if who == self then + print("哇!") + else + if who == self:right() then + print("鄙视下定") + else + print("emmm...") + end + end +end +``` +这段代码的意思是: + +- 如果摸牌的人是自己: + - 输出「哇!」 +- 否则: + - 如果摸牌的人是自己的下家: + - 输出「鄙视下家」 + - 否则: + - 输出「emmm...」 + +就像上面的例子所展示的一样,`if`里面可以嵌套`if`。 +我们不妨再套一层,让它在对家摸牌时输出「嫌弃对家x」。 + +```lua +function ondraw() + if who == self then + print("哇!") + else + if who == self:right() then + print("鄙视下定") + else + if who == self:cross() then + print("嫌弃对家x") + else + print("emmm...") + end + end + end +end +``` + +道理很简单,就是一级一级地判断 —— +但是这画风太鬼畜了,看着就晕,尤其是最后的`end`四连,简直洗脑x + +好在 Lua 提供了一种方便的写法 —— `elseif`: + +```lua +function ondraw() + if who == self then + print("哇!") + elseif who == self:right() then + print("鄙视下定") + elseif who == self:cross() then + print("嫌弃对家x") + else + print("emmm...") + end +end +``` + +通过`elseif`,代码的逻辑没有变,但看起来舒服了很多,也避免了鬼畜的`end`四连。 + +虽然我们已经用过很过次`ondraw`函数和`if`语句了, +但里面的很多东西其实都没讲清楚,下面详细补充一下。 + +
+ +## 解释器的工作方式 + +先解释一下松饼 Lua 解释器的工作方式。 + +每一个角色都运行在独立的环境里, +它们之间无法直接通过共享全局变量来串通。 + +在一桌开始时,系统会把在场人物的 Lua 文件都运行一遍, +这个过程我们姑且称为「初始化」。 +在初始化期间,代码可以定义一些全局函数,准备一些全局变量。 +这个时候也可以定义局部变量,搞一些计算 —— +初始化结束后,全局变量会被保留。 + +想要实现摸牌挂,就要定义`ondraw`全局变量,其类型为函数。 +过后,每当有人摸牌时,解释器都会在摸牌之前先调用`ondraw`。 + +`ondraw`的定义内部可使用`who`,`self`等全局变量。 +这些变量是由系统从外部直接塞进来的,拿来用就行了。 + +
+ +## if 的工作方式 + +最简单的`if`语句长这个样子: + +```lua +if 条件 then + 语句1 + 语句2 + 语句3 + ... +end +``` + +「条件」的求值结果为「真」,则执行里面的那堆语句(称做「语句体」), +「条件」为「假」时则会跳过语句体,执行`end`后面的代码。 + +if 语句可以有 else 部分和/或 elseif 部分: + +```lua +if 条件1 then + 语句体1 +elseif 条件2 then + 语句体2 +elseif 条件3 then + 语句体3 +else + 语句体N +end +``` + +这种情况下,会先计算「条件1」。 +「条件1」为「真」,则执行「语句体1」。 +「条件1」为「假」,则继续计算「条件2」,以此类推。 +这里需要注意的是计算的顺序。如果前面的条件为「真」, +后面的条件就不会被计算。 + +每一个语句体都会开启一个新的局部变量的作用域(即「块」)。 + +在 Lua 中,boolean 类型的`false`,和 nil 类型的`nil`是「假」, +其余的任何类型的任何值都是「真」。 +这意味着 number 类型的`0`,string 类型的`""`也都是「真」。 + +
+ +## for 循环 + +
+ +## while 和 repeat 循环 + +
+ +## 逻辑运算 + +
+ +## 练习题 + +1) 判断以下表达式真假: +```lua +nil == "nil" or nil +nil == ("nil" and nil) +1 + 1 == 2 or nil +1 + 1 ~= (2 or nil) +(0 and true) and T34.new("3y") or false +``` + +下一讲:[表](/docs/editor/table/) + diff --git a/docs/editor/func.md b/docs/editor/func.md index 6206e12..f43ef01 100644 --- a/docs/editor/func.md +++ b/docs/editor/func.md @@ -9,18 +9,35 @@ permalink: /docs/editor/func/ ## 上一讲的习题参考答案 1) `a`, `b`, `c`满天飞,滥用隐式类型转换(等等) -2) 合法:`doge`, 非法:`good-doge` +2) 合法:`doge`, 非法:`good-doge`(因为有中划线) 3) number, string, nil, boolean 4) `false`
-## 函数 - -函数是确保代码可维护性的重要手段之一。 +## 可维护性了解一下 所谓「可维护」,就是指改起来方便。 -代码改起来方不方便,可以决定项目的生死。 +改起来方便的代码会越改越好, +而改起来不方便的代码则吃枣药丸。 + +很多学生党写代码都不怎么重视可维护性。 +这是因为他们写的东西,无论是作业、课题还是竞赛中提交的答案, +都是「一次性」的代码 —— 今天完成任务以后,明天就再也不用改了。 +对于一次性代码来讲,可维护性自然并不重要; +但如果想写一个真正「有用」的东西,就不能这么玩了 —— +因为这些东西将来是要反复修改的 —— 加功能、调细节、改 bug。 +若不重视可维护性, +每当想新增一些功能、调整一些细节、修复一些 bug 的时候, +都会分分钟突然失去梦想x + +所以可维护性大法好。 + +
+ +## 函数 + +通过函数,可以简单粗暴地提高代码的可维护性。 举一个粟子: @@ -89,8 +106,10 @@ poetize("姬子") ``` 三狗测试,见以上代码又吹我爽,又吹军师,又吹龙华,又吹姬子。 +每吹一人,都只需简单加上一行代码。 +只要愿意,甚至可以随时来上一句`poetize("京狗")`,十分方便。 如果不用函数,这么一波吹下来,得写上大量的重复代码, -不旦写着麻烦,将来改起来也麻烦。 +不旦写着麻烦,看着不爽,将来改起来也麻烦。 所以,函数大法好。 多用函数,简化代码,延年益寿,岂不美哉x @@ -112,8 +131,7 @@ poetize("军师") 这段代码定义了一个叫`poetize`的函数, 然后以`"军师"`为参数调用了一下它。 -- 定义函数时,先写`function`,再写函数名, - 再写「参数列表」,再写定义的内容,最后写`end`。 +- 定义函数时,需要在函数名后面加一个「参数列表」。 所谓「参数列表」,就是一个括号,里面写上任意个变量名。 本例中我们只写了一个`name`变量。 - 调用函数时,先写函数名,再加个括号, @@ -133,12 +151,61 @@ poetize("军师", "x") poetize("军师", "!") ``` +函数也可以没有参数。 +定义和调用没有参数的函数的时候,在函数名后面加一对空的括号: + +```lua +function poetize() + print("我爽美如画") +end + +poetize() +``` +
## 返回值 -函数是可以「返回」值的。 +函数可以有一个计算结果,比如: + +```lua +function plus1(x) + return x + 1; +end + +print(plus1(2)) +``` + +结果输出 3。 +这里我们用到了`return` —— +`return`就是给出这个函数的计算结果。 + +不过之前「我爽」的那个函数里没有`return`。 +在 Lua 中,函数可以有`return`,也可以没有`return`。 +没有`return`函数计算结果为`nil`: + +```lua +function f(x) +end + +a = f(2) +print(a) +``` + +结果输出 `nil`。另外`return`后面不加表达式时,计算结果也是`nil`: + +```lua +function f(x) + return +end + +a = f(2) +print(a) +``` + +`return`意为「返回」,函数的计算结果也叫「返回值」。 「返回」的意思是说,哪儿来的回哪儿去。 +举个栗子: ```lua function f(x) @@ -156,15 +223,156 @@ print(g("我爽")) 三狗测试,见输出「我爽我爽美如画!」。 这个「我爽我爽美如画!」是怎么算出来的呢? -首先,这个输出肯定是从`print`那里出来的, -也就是说,那个`g("我爽")`的值就是`"我爽我爽美如画!"`。 -那么`g("我爽")`的值又为什么是`"我爽我爽美如画!"`? +这段代码干了三件事: + +1. 定义`f`函数 +2. 定义`g`函数 +3. 调用`print`函数 + +其中,定义函数是不会产生输出的, +产生输出的是最后的`print`那一行代码: +``` +print(g("我爽")) +``` + +在 Lua 中,调用一个函数之前,会先把参数的值求出来。 +所以在执行到`print(g("我爽"))`时, +会先去求`g("我爽")`的值,再用求出来的结果去继续调用`print`。 + +于是这段代码接下来就会跳到`g`的定义,开始求`g("我爽")`的值。 +`g`的定义一共有两行,其中第一行为: +```lua +y = f(x) .. "美如画" +``` +由于我们传入的`x`是`"我爽"`,这一行此时相当于是: +```lua +y = f("我爽") .. "美如画" +``` +也就是将`f("我爽")`和`"美如画"`拼接成一个新的字符串,赋值给`y`。 +为了得到这个拼接的结果, +Lua 接下来会先去求`f("我爽")`的值。 +于是我们跳到的`f`的定义。`f`的定义里只有一行: +```lua +return x .. x +``` +由于我们传入的`x`是`"我爽"`,这一行相当于: +```lua +return "我爽" .. "我爽" +``` +也就是: +```lua +return "我爽我爽" +``` +`return`后面的表达式的求值结果,就是这个函数的求值结果。 +接下来就是把这个结果「返回」的时候了。 +返回结谁?从哪儿来的,就返回给谁。 +刚才是从这一行来的: +```lua +y = f("我爽") .. "美如画" +``` +现在`f("我爽")`的值求完了,这一行也就成了: +```lua +y = "我爽我爽" .. "美如画" +``` +也就是: +```lua +y = "我爽我爽美如画" +``` +接下来,继续执行`g`的后面一行: +```lua +return y .. "!" +``` +这行现在相当于: +```lua +return "我爽我爽美如画" .. "!" +``` +也就是: +```lua +return "我爽我爽美如画!" +``` +接着,再把这个结果返回给当初调用`g`的地方,也就是`print`那一行: +``` +print(g("我爽")) +``` +现在相当于: +``` +print("我爽我爽美如画!") +``` +于是这段代码最终输出了「我爽我爽美如画!」。 + +
+ +## 提前返回 + +`return`语句通常写在函数结尾,但也可以提前出现。 +`return`出现在函数中途时,函数后面的部分都会被跳过, +直接返回到调用函数的地方。 + +提前返回常用于错误处理:见事不好,调头就跑。 + +```lua +function f(name) + if name == "京狗" then + print("帅哥你谁啊") + return + end + + print(name .. "美如画") +end + +f("我爽") +f("京狗") +``` -这得看`g`这个函数是怎么定义的。 +测试知先后输出「我爽美如画」和「帅哥你谁啊」。 +当输入参数为京狗时,美如画的部分并没有被执行。 -(TODO) +提前返回有助于提早排除有毒的输入参数, +减少缩进层级,使后面的代码写起来更爽。
-## 局部变量 +## 练习题 + +1) 预测以下代码输出: +```lua +function f(x) + return x + 1 +end + +function g(x) + return 2 * f(x) +end + +a = f(1) + g(2) +print(a) +``` + +2) 预测以下代码输出: +```lua +function f() + print("f1") + return "f2" +end + +function g() + print("g1") + print(f()) + print("g2") +end + +g() +``` + +3) 完成`repeat3`的定义,使代码输出「嗷嗷嗷」。 + +```lua +function repeat3(str) + -- TODO 在此处填写实现 +end + +print(repeat3("嗷")) +``` + +下一讲:[局部变量](/docs/editor/local/) diff --git a/docs/editor/local.md b/docs/editor/local.md new file mode 100644 index 0000000..0897537 --- /dev/null +++ b/docs/editor/local.md @@ -0,0 +1,335 @@ +--- +layout: page +title: 局部变量 +permalink: /docs/editor/local/ +--- + +「松饼人物编辑器:从入门到欧耶」系列教程(四) + +## 上一讲的习题参考答案 + +1) 抄代码运行即可验证 +2) 抄代码运行即可验证 +3) 一个参考: +```lua +function repeat3(str) + return str .. str .. str +end + +print(repeat3("嗷")) +``` +
+ +## 脑容量问题 + +写代码时,我们会不断地「起名字」 +—— 有时给变量起名,有时又给函数起名。 +起的名字越多,记忆的负担也就越大 —— +我们需要记住,这个函数是干什么的,那个变量又是干什么的。 +有时候,可能会由于疏忽,把某个已经有了某个用途名字, +当成一个新名字用到另一个用途上 —— +两块功能交替使用一个名字,结果出了一堆奇怪的错误。 + +举个粟子: + +```lua +function repeat2(x) + a = x .. x + return a +end + +a = "哇" +b = repeat2("哈") +print(a .. b) +``` + +首先,定义一个把字符串重复 2 次的函数`repeat2`。 +然后,`a`是「哇」,`b`是重复两次的「哈」,打印`a .. b`。 +结果会输出什么? + +> 肯定是「哇哈哈」啊,这种局面还看不懂吗? + +(测试见输出「哈哈哈哈」) + +> …枼?…别啊?!哎~!呀~!这解说不下去了,哎呀这!!呃啊~~ + +(为什么会变成这样呢……) + +要想修正这个问题,要么`repeat2`里别用`a`,要么外面别用`a`。 +总之就是只能有一个地方能用`a`。 +不管代码写得多长,都得记住`a`是给哪一段代码用的 —— +除了那段代码,其它地方都不能用`a`。 + +这就坑爹了。你得记住每一个变量名都是用在哪里的,不论代码有多长。 +这是想把人脑袋撑爆啊x + +所以,局部变量大法好。 + +
+ +## 关键字 local + +用`local`大法,将刚才的代码改写如下: + +```lua +function repeat2(x) + local a = x .. x + return a +end + +a = "哇" +b = repeat2("哈") +print(a .. b) +``` + +测试见输出「哇哈哈」。 + +对一个变量赋值前,前面加上`local`, +表明被赋值的变量是一个新创建的「局部变量」。 + +局部变量,就是只在局部有效的变量。 +比如你在麻吧里说「老板」,指的肯定就是照老板, +不是其它的什么老板。 +这个时候,「麻吧」就是一个「局部」,在这个局部里,「老板」特指这个局部里的照老板。 + +在`repeat2`函数中,由于`a`被声明成了一个局部变量, +在`repeat2`内的`a`指的都是`repeat2`里的这个`a`, +跟外面`a = "哇"`的那个`a`就完全没关系了。 + +
+ +## 作用域 + +局部变量从对应的`local`那一行开始可以用, +到声明了这个`local`所在的「块」的结束就不能再用了。 +所谓的「块」,可以是函数,也可以是`if`语句,也可以是以后介绍的其它东西。 +习惯上,每进入一个新的「块」,都会增加一级缩进。 + +在一个「块」里使用一个名字时, +如果这个「块」里有叫这个名字的局部变量, +那么这个名字指的就是这个局部变量。 +如果这个「块」里没有叫这个名的局部变量, +这个名字指的就是外面的「块」里的局部变量。 +外面的「块」还没有,就到外面的外面的「块」里去找。 +如果连最外面的「块」里也没有,这个名字指的就是全局变量。 + +举个粟子: + +```lua +function f() + print(a) -- A + local a = 1 + print(a) -- B + if true then + print(a) -- C + local a = 2 + print(a) -- D + end + print(a) -- E +end + +f() +``` + +以上代码先后输出 nil, 1, 1, 2, 1。 + +从`--`到行尾的文字叫做「注释」,会被机器无视掉,是写给人看的。 +这里我们注释标出了 A, B, C, D, E 五个行,以便于说明。 + +执行到 A 行的时候,当前代码所在的「块」就是函数`f`。 +这个「块」里还没有局部变量`a`,所以这个`a`指的是外面的`a`。 +外面也没有`a`,所以这里的`a`是个全局变量。 +我们没有碰过全局变量`a`,所以此行输出 nil。 + +执行到 B 行的时候,当前的「块」里已经有局部变量`a`了,值为 1,所以输出1。 + +执行到 C 行的时候,`if`语句开启了一个新的「块」。 +当前「块」里没有`a`,所以这里的`a`指的是外面的「块」里的`a`, +也就是 1。 + +执行到 D 行的时候,`if`「块」里也有了`a`,值为 2。 +所以此时的`a`指的就是这个`if`里新建的`a`。 + +到了 E 行,已经退出了`if`「块」,所以`if`里的那个`a`已经没了。 +现在的`a`指的是函数「块」里的`a`,也就是 1。 + +
+ +## 疯狂使用局部变量 + +局部变量不但可以节约人的脑容量, +还可以提高代码的运行速度(原理不展开)。 +所以`local`关键字应该能加就加。 + +另外很多人都提倡尽可能在靠「内」的块里声明变量。 +举个粟子: + +```lua +function f() + local a = 1 + if true then + print(a) + end +end +``` +```lua +function f() + if true then + local a = 1 + print(a) + end +end +``` + +上面的两段代码所做的事情是相同的,但第二段代码读起来更舒服。 +第一段代码中,`if`外面明明没有用到`a`,却把`a`放到了`if`外面,愣是增加了理解的难度。 + +
+ +## 函数的参数 + +函数的参数虽然不带`local`字样,但都是局部变量,只在函数内有效。 + +调用函数的时候,传的是「值」 +—— 值会被复制一份,对复制品的操作影响不到原品。 + +```lua +function f(x) + x = 2 +end + +a = 1 +f(a) +print(a) +``` + +上面的代码输出 1,而不是 2。在调用`f(a)`的时候,`a`的「值」 +—— 也就是 1 —— 被复制了一份给局部变量`x`。 +随后`x`这个局部变量被改成了 2,但这跟`a`有什么关系?所以最终输出 1。 + +```lua +function f(a) + a = 2 +end + +a = 1 +f(a) +print(a) +``` + +上面的代码仍然输出 1。参数的名字被改成了`a`, +但它也是一个仅在函数内存在的局部变量,跟外面的那个`a`没关系。 + +
+ +## 上值与闭包 + +和其它的变量一样,函数也是可以在局部随时创建的: + +```lua +function f() + local function g() + print("a") + end + + g() +end + +f() +``` + +在函数的定义内,可以访问外部的局部变量。 +函数内使用到的外部的局部变量,叫「上值」。 + +```lua +function f() + local str = "a" + local function g() + print(str) -- str是g的一个上值 + end + + g() +end + +f() +``` + +我们可以在函数里定义新函数并返回出去,达到用函数去创建函数的目的: + +```lua +function make() + local str = "a" + local function g() + print(str) + end + + return g -- 返回一个函数g +end + +local h = make() -- 通过make函数创建h函数 +h() -- 调用h函数 +``` + +每执行一次`function`与`end`之间的部分, +都会产生一个新的函数。举个粟子: + +```lua +function make() + local i = 1 + local function g(x) + print(i) + i = x + end + + return g +end + +local h1 = make() +local h2 = make() + +h1(233) +h2(666) + +h1(0) +h2(0) +``` + +测试见依次输出 1, 1, 233, 666。 +这可以证明`h1`和`h2`里面的上值`i`虽然名字相同, +但并不是同一个变量。 +这是因为,`h1`与`h2`是在两次`make`的调用中创建的 —— +每次调用`make`,都会创建一个新的局部变量`i`。 +随后,又创建新的函数`g`,这个新的函数引用了刚刚新建的`i`。 +所以`h1`与`h2`中的`i`指的就是两个不同的变量。 + +可见,一个函数不仅代表一堆指令,还可以拥有只属于自己的一堆上值, +就好像带着一个小包包一样。 +像这种带着包的函数,通常叫「闭包」。 +上面的例子中,函数`h1`和`h2`的定义虽然相同,但它们是两个不同的闭包。 + +松饼的官方范例与之后的教程中,闭包并不常用; +对于人物编辑而言,闭包也不是刚需。 +但为了避免写出 bug,或产生奇怪的误解, +上值与闭包的基本概念还是必须要掌握的。 + +
+ +## 练习题 + +1) 判断题:「局部变量是给笨蛋用的,记忆力好的人不需要用局部变量。」 +2) 有些人喜欢把所有的局部变量声明写在函数开头,觉得这样很「清晰」, + 对此你怎么看? +3) 完成`make`函数的定义,使代码先后输出「嗷」、「嗷嗷」、「嗷嗷嗷」。 +```lua +function make(unit) + -- TODO 填写实现 +end + +ao = make("嗷") +ao() +ao() +ao() +``` + +下一讲:[userdata](/docs/editor/userdata/) + diff --git a/docs/editor/start.md b/docs/editor/start.md index 779a304..8bbb160 100644 --- a/docs/editor/start.md +++ b/docs/editor/start.md @@ -135,23 +135,23 @@ print("Vanishmennt this world!") ```lua function ondraw() - print("waaah!!") + print("哇!") end ``` -三狗战测试,发现每当有人摸牌时都会输出一次「waaah!!」。 +三狗战测试,发现每当有人摸牌时都会输出一次「哇!!」。 这意味着,我们成功地实现了一个完整的摸牌挂 —— 每次摸牌时,这个挂都会生效 —— 虽然只是打印一行字。 不过多数情况下,自己的进张和他家的进张需要区别对待 —— 比如给自己塞有效牌,给他家塞铳牌什么的。 所以我们继续改进代码,让程序区另对待自己和他家的摸牌 —— -自己摸牌时输出「waaaah!!」,而他家摸牌时输出「emmmm...」。 +自己摸牌时输出「哇!」,而他家摸牌时输出「emmmm...」。 ```lua function ondraw() if who == self then - print("waaah!!") + print("哇!") else print("emmm...") end @@ -171,7 +171,7 @@ end ```lua function ondraw() - print("waaah!!") + print("哇!") end ``` @@ -192,7 +192,7 @@ end ```lua function ondraw() if who == self then - print("waaah!!") + print("哇!") else print("emmm...") end @@ -229,7 +229,7 @@ end ```lua function ondraw() if who == self then -print("waaah!!") +print("哇!") else print("emmm...") end diff --git a/docs/editor/userdata.md b/docs/editor/userdata.md new file mode 100644 index 0000000..d2c55af --- /dev/null +++ b/docs/editor/userdata.md @@ -0,0 +1,208 @@ +--- +layout: page +title: userdata +permalink: /docs/editor/userdata/ +--- + +「松饼人物编辑器:从入门到欧耶」系列教程(五) + +## 上一讲的习题参考答案 + +1) 狗带(你慢慢记忆力良好x) +2) 不符合多数人的习惯,所谓「清晰」也是主观的 +3) 一种可能的实现: + +```lua +function make(unit) + local sum = unit + return function() + print(sum) + sum = sum .. unit + end +end + +ao = make("嗷") +ao() +ao() +ao() +``` +
+ +## 使用松饼 userdata + +自从第二讲以来,好久没做人物技能了,一直都在写诗什么的x + +为了尽快切入我们的核心主题 —— 人物技能, +这里我们要掌握基本的松饼 userdata 的用法。 + +先回忆一下 Lua 中的七种数据类型: + +- number +- string +- boolean +- table +- function +- userdata +- nil + +其中我们没有直接用过的就剩 table 和 userdata 了。 +table 的用法以后再说,这里先看 userdata。 + +userdata 与其它的类型有一点区别。 +其它的类型,都是 Lua 语言自带的, +而 userdata 则是由应用(大环境)添加的。 +在松饼大环境下,userdata 就是麻将牌、牌山、牌桌这些东西。 +尽管同样是 Lua 语言,由于应用不同,使用 userdata 的方式也略有差异。 +为方便说明,下文中的 userdata 将特指松饼中的 userdata。 + +
+ +## 麻将牌 T34 + +松饼中有两种代表麻将牌的类型:`T34`与`T37`。 +区别在于后者将赤宝牌与普通的数牌 5 视为不同的类型。 +这里我们先看更常用的`T34`。 + +写下`local i = 1`,就创建了一个 number 变量`i`; +写下`local s = "xxx"`,就创建了一个 string 类型的`s`; +写下`local b = true`,就创建了一个 boolean 类型的变量`b`。 +类似地,我们可以通过如下写法,创建一个「麻将牌」类型的变量`t`: + +```lua +local t = T34.new("1s") +``` + +你会发现,创建麻将牌的写法, +比创建 number, string, boolean 的写法要麻烦得多。 +这是理所当然的,毕竟麻将牌不是 Lua 的亲儿子, +而是由松饼加进去的 userdata 类型。 + +松饼对 userdata 类型进行了细化, +将其分为`T34`, `Mount`, `Who`, `Game`等具体的类型, +每个类型都有不同的用处,比如`T34`代表麻将牌,`Mount`代表牌山等等。 +我们先了解一下`T34`的用法。 + +上面的例子中,`t`是一个`T34`类型的变量,其值为「一索」。 +`T34.new`其实就是一个函数, +通过一个 string 类型的参数(上面的例子中的`"1s"`)指定想要创建的牌。 +这个 string 应该由两个字符组成, +第一个字符代表牌的数值,第二个字符代表牌的花色, +比如`"1s"`, `"7p"`, `"5m"`等等。 +在松饼中,万子、饼子、索子、风牌、三元牌分别用 +`m`, `p`, `s`, `f`, `y` 表示。 +风牌的数值为东1、南2、西3、北4;三元牌的数值为白1、发2、中3。 +比如,下面的代码创建了代表二饼和白板的变量`t1`与`t2`: + +```lua +local t1 = T34.new("2p") +local t2 = T34.new("1y") +``` + +至于`T34`和`new`中间的那个点「`.`」是个什么鬼,我们以后再解释。 + +
+ +## 身份 Who + +几乎所有的技能都是「对人」的。 +比如「谁听牌我坑谁」,「自己加速、他家减速」,「专坑下家二十年」等等。 +要想在代码中表达这个「谁」的概念,就要用到`Who`这个 userdata 类型。 + +`Who`和`T34`有一点区别: +`T34`可以通过`T34.new`函数来创建, +而`Who`无法在 Lua 里凭空创建, +只能使用已经由系统创建好的的变量。 +其实我们已经用过好几次`who`类型的变量了 —— +之前在`ondraw`函数中常用的`who`和`self`变量就都是`Who`类型的。 +每当系统在调用`ondraw`之前,都会设置好这两个全局变量: + +```lua +function ondraw() + if who ~= self then + return + end + + print("哇!") +end +``` + +上面的写法是一种很常见的摸牌挂套路。 +首先,通过`who ~= self`判断`who`与`self`是否「不相等」。 +`~=`与`==`的作用刚好相反,在两侧不相等时得`true`,相等时得`false`。 +若`who`不等于`self`,则提前返回 —— +这就导致了`ondraw`后半部分的代码只会在`who`为`self`的情况下执行, +使得该技能只会影响自己的进张。 + +`self`表示自己,那自己的下家、对家、上家又怎么表示呢? + +松饼提供了三个函数:`Who.right`, `Who.cross`, `Who.left`, +分别可用于求出一个`Who`类型变量的下家、对家、或上家 —— +只要把作为基准的`Who`变量作为参数传入即可: + +```lua +function ondraw() + if who ~= Who.right(self) then + return + end + + print("坑坑坑坑坑") +end +``` + +三狗测试知以上人物在下家摸牌时输出「坑坑坑坑坑」。 + +
+ +## 方法调用 + +下面的两种写法作用是相同的: + +```lua +Who.right(self) -- 写法1 +self:right() -- 写法2 +``` + +这两种写法都表示「自己的下家」。 +「写法 2」只是「写法 1」的简略版本,没什么深奥的区别。 +这种带冒号的写法, +等同于把冒号前面的 userdata 作为第一个参数传入冒号后面的函数。 +冒号后面的函数名,指代的是与这种 userdata 配套使用的那个函数 —— +在上面的例子中,`self:right()`中的`right`实际代表`Who.right`。 + +与某种 userdata 类型配套使用的函数,也叫作「方法」。 +不同的类型,有不同的方法。 +可以说,正是因为方法的不同,才使得类型得以不同。 +食物可以吃,可以煮;衣服可以穿,可以脱。 +因为可以吃,可以煮,所以才称得上是食物; +因为可以穿,可以脱,所以才称得上是衣服。 + +至于每一种类型具体都有哪些方法, +可在需要时参考 [API 文档](/docs/editor/api/),无须刻意记忆。 + +
+ +## 基本牌山干涉 + +(TODO) +[mount](/docs/libsaki/mount/) +1. examples `lighta` +2. simple logging + +
+ +## 练习题 + +1) 预测各家摸牌前的输出: +```lua +function ondraw() + print(who:right():right() == self:left()) +end +``` + +自己摸牌前输出( ), +下家摸牌前输出( ), +对家摸牌前输出( ), +上家摸牌前输出( )。 + +下一讲:[控制流](/docs/editor/flow/) + diff --git a/docs/editor/var.md b/docs/editor/var.md index a41a7a9..a311b94 100644 --- a/docs/editor/var.md +++ b/docs/editor/var.md @@ -136,7 +136,6 @@ print(3 + 2 * (2 - 3)) 写下一行代码时,不光要考虑到这行代码是否满足眼下的需要, 更要考虑到将来是否可能会累死、是否可能会手滑。 人不能自己给自己挖坑。 -项目规模大到一定程度以后,人这种动物就会变得比想象中的要脆弱得多。 上面的例子中的表达式里用到了括号。 有些时候,即使是不影响计算的优先级,也会多加几个括号 —— @@ -171,7 +170,7 @@ print(Emmm) 上面的代码输出 2333 和 66666,可见`emmm`和`Emmm`是两个不同的变量。 变量名可以由字母、数字、和下划线组成,同时不能以数字开头。 -虽然可以用大写,但习惯上一般只用小写变量名。 +虽然可以用大写,但习惯上(至少在 Lua 标准库中)一般只用小写变量名。 在三次元中,你可以给你家的狗起名为`if`, 但在 Lua 中这是非法的 —— `if`这个词已经被 Lua 保留了, @@ -366,5 +365,5 @@ d = a == b 4) (附加题)上一题的代码执行后,`d`的值是什么? -下一讲:(施工中) +下一讲:[函数](/docs/editor/func/) diff --git a/docs/girl.md b/docs/girl.md index f4e05f2..59effe7 100644 --- a/docs/girl.md +++ b/docs/girl.md @@ -14,30 +14,31 @@ permalink: /docs/girl/ {% endfor %}

-
- ## 正片 ----- + + {% for girl in site.data.girls %} -

{{ girl.name }}

-{% for skill in girl.skills %} -

{{ skill.name }}

-
    -{% for desc in skill.descs %} -
  • {{ desc.content }} -{% if desc.subdescs %} -
      -{% for subdesc in desc.subdescs %} -
    • {{ subdesc }}
    • -{% endfor %} -
  • -{% else %} - -{% endif %} +
+ + + {% endfor %} - -{% endfor %} ----- -{% endfor %} - +
{{ girl.name }} + + {% for skill in girl.skills %} + {{ skill.name }} +
    + {% for desc in skill.descs %} +
  • + {{ desc.content }} + {% if desc.subdescs %} +
      + {% for subdesc in desc.subdescs %}
    • {{ subdesc }}
    • {% endfor %} +
    + {% endif %} +
  • + {% endfor %} +
+ {% endfor %} +
diff --git a/docs/libsaki/mount.md b/docs/libsaki/mount.md index 8b723f1..563e095 100644 --- a/docs/libsaki/mount.md +++ b/docs/libsaki/mount.md @@ -22,7 +22,7 @@ permalink: /docs/libsaki/mount/ 这种直接改概率的方式是最容易想到的, 然而存在一个致命的问题,就是多个能力的叠加与兼容会变得复杂。 -例如,现在轮到A摸牌。A的技能规定:此时A有80%在概率自摸。 +例如,现在轮到A摸牌。A的技能规定:此时A有80%的概率自摸。 而另一个人物B的技能规定:此时A有90%的概率摸到B的铳牌。 那么结果A到底应该摸到什么呢? diff --git a/docs/phil.md b/docs/phil.md index 7ddf8de..49d4c62 100644 --- a/docs/phil.md +++ b/docs/phil.md @@ -55,8 +55,9 @@ permalink: /docs/phil/ 1. 不支持犯规操作 1. 无役/振听时默默地没收和牌按钮 + - 要啥提示,要啥提示,没算成诈和扣分就不错了 1. 模仿实体麻将 - 1. 不显示宝牌底色、振听提示等实麻中不存在的东西 + 1. 不显示宝牌底色等实麻中不存在的东西 2. 自摸切/手切,鸣牌巡目只能在当时区分,过后只能自行记忆 3. 鸣牌/食和前应当没空犹豫,错过了就错过了 diff --git a/docs/rule.md b/docs/rule.md index d8f1dd8..ae5328b 100644 --- a/docs/rule.md +++ b/docs/rule.md @@ -65,8 +65,10 @@ permalink: /docs/rule/ ## 讨规约定 我们只接受两种有关规则的改动意见: -- 现有规则和原作存在冲突 -- 现有规则过于稀有,不曾有人提及过 +1. 现有规则和原作主线剧情存在冲突 + - 此处「原作」特指本篇、阿篇、慕篇漫画, + 不包括怜篇、动画、真人版、游戏 +2. 现有规则过于稀有,不曾有人提及过 -“和天凤不一样”等理由是不接受的。 +「和天凤不一样」等理由是不接受的。 diff --git a/docs/start.md b/docs/start.md index ffe6594..adba88c 100644 --- a/docs/start.md +++ b/docs/start.md @@ -8,9 +8,7 @@ permalink: /docs/start/ 不怕神对手,只怕猪队友——我们希望所有的项目参与者都能认真读完本文。 -
- -## 1. 关于Git +## 1. 关于 Git 松饼开发者必须熟悉Git。 如果没听说过、或不熟悉Git,可参考以下教程: @@ -20,15 +18,13 @@ permalink: /docs/start/ 2. 巩固补充(必修):[Ruheng的Git教程][git-adv]{:target="_blank"} (学习时长:一至三天) 3. 深入(选修):[Pro Git (中文版)][pro-git]{:target="_blank"} - (学习时长:长期) - -
+ (学习时长:长期) ## 2. 关于 Gitter 松饼开发者之间通过 Gitter 交流。 -Gitter 是一个聊天工具,可私信可群聊。 +Gitter 是一个聊天工具。 由于支持 Markdown 语法,并且可以和各类开发工具联动, 所以很适合有关编程的讨论。 Gitter 有网页版、桌面版、手机版,基本上什么系统都支持。 @@ -36,9 +32,7 @@ Gitter 有网页版、桌面版、手机版,基本上什么系统都支持。 - 松饼 Gitter 群链接: [mjpancake]({{ site.data.link.gitter }}){:target="_blank"} -
- -## 3. 松饼是用什么做出来的 +## 3. 项目构成 「松饼」总共包含四个项目:核心库、客户端、服务器、主站。 四个项目关系如图。 @@ -54,32 +48,25 @@ GitHub 地址: - [`rolevax/ih`][ih] - [`mjpancake/mjpancake.github.io`][pages] -
- ## 4. 开发环境的搭建步骤 见 [搭建开发环境](/docs/dev-setup/) 页面。 -
- -## 5. 工作流程 +## 5. 大致工作流程与审查标准 -- 第一步,从`upstream/develop`创建新分支 - - `git fetch upstream` - - `git checkout -b my-skill upstream/develop` +- 第一步,从`develop`创建新分支 - 第二步,写代码,测试结果 - - 根据[松饼C++规范](/docs/cpp/)整理改动过的代码 - 第三步,提交并上传 - - `git commit -am "add xxxxx skill"` - - `git push -u origin my-skill` -- 第四步,创建 pull request 并等待审查 - - 合并目标是`develop`分支 +- 第四步,创建合并至`devleop`分支的 pull request 并等待审查 - 第五步,根据审查结果修改代码,提交上传并等待再次审查 - - `git commit -am "improve xxxxx skill"` - - `git push` - 重复第五步直到分支被合并 +明文审查标准: + +- [松饼 C++ 代码规范](/docs/cpp/) +- [松饼 QML 代码规范](/docs/qml/) +除明文标准外,还会有基于常识的考虑要素。 [lxf]: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 [git-adv]: https://www.jianshu.com/p/072587b47515 diff --git a/feedback.md b/feedback.md index 073623d..609363f 100644 --- a/feedback.md +++ b/feedback.md @@ -24,8 +24,6 @@ permalink: /feedback/ 注意: -- 有价值的 bug/错字 反馈可获得 0~500 贡献度 - - [贡献度是什么?](/contribute/) - 如果是有关牌局的 bug,附上牌谱截图 - 截图需完整包含整张牌桌,不要裁剪 diff --git a/index.md b/index.md index d657ef0..29b31ba 100644 --- a/index.md +++ b/index.md @@ -5,50 +5,90 @@ title: "松饼社区主站" # 松饼麻雀简介 -「松饼麻雀」是一个 Saki 麻将模拟器,和官方游戏区别如下: +「松饼麻雀」是一个 Saki 世界观麻将模拟器, +由一群麻吧吧友和 AI 喵打共同制作。 + +我们和官方游戏区别如下: |-------------------|-------------------------|-----------| -| 对比项目 | 松饼麻雀 | 官方游戏 | +| | 松饼麻雀 | 官方游戏 | |-------------------|-------------------------|-----------| -| 平台 | 电脑/手机/平板 | PSP/PSV | | 原作技能还原度 | 哇!!! | emmmm... | -| 开放世界/可定制性 | 哇!!! | emmmm... | -| 慕篇人物 | 哇!!! | emmmm... | -| 慕篇规则 | 哇!!! | emmmm... | -| 临海、有珠山人物 | 哇!!! | emmmm... | +| 人物编辑器 | 哇!!! | emmmm... | +| 慕篇、临海、有珠山人物 | 哇!!! | emmmm... | +| 流年规则 | 哇!!! | emmmm... | +| 支持平台 |Windows, Android, Linux, macOS, iOS|PSP, PSV | |-------------------|-------------------------|-----------| -
-总结起来,就是: -> 一堆平台,五个「哇!!!」 +某截图: ---- -
+(准备中) -# 如何入坑 +牌桌背景和人物头像可随意替换。 +目前的 UI 是临时凑合用的,将来会弃用传统的 2D 俯视牌桌, +改用类似原作漫画的分镜式界面。 -入坑5大要素: +# 下载松饼麻雀 -1. [注册](/signup/) -2. 加群 253708512 (Q) -3. [下载]({{ site.data.link.releases }}) -4. [看攻略](/docs/) -5. [参与](/contribute/) +- [点击进入下载页面]({{ site.data.link.releases }}){:target="_blank"} + +- 下载最上面的最新版即可 +- 以上链接为目前唯一的官方下载途径 + - 通过其它途径下载的很有可能是魔改版 +- 系统要求: + - Windows: 7 或以上(不支持 XP 和 Vista) + - Android: 4.1 或以上 + - Linux, macOS, iOS: 主流版本均可,需自行编译 + +# 关于 ID + +- [注册松饼 ID](/signup/) + +# 讨论/提问 + +- 官方企鹅群:253708512 + - 加了这个群,就可以愉♂悦地讨论、提问了 —— 还能及时获得各种一手情报。 +- 意见、建议、或 bug 报告:前往[「反馈」](/feedback/)页面。 +- 松饼麻雀全栈开源,欢迎 dalao 参与开发 + —— 详见下方[「开发者 RTFM 系列」](#rtfm)一节。 + +# 食用手册 + +- [能力表](/docs/girl/) +- [麻将规则](/docs/rule/) +- [设计哲♂学](/docs/phil/) +- [还原度对照表](/docs/target/) + +# 人物编辑器 + +「松饼人物编辑器:从入门到欧耶」系列教程: + +- [搞起](/docs/editor/start/) +- [数据类型](/docs/editor/var/) +- [函数](/docs/editor/func/) +- [局部变量](/docs/editor/local/) +- [userdata](/docs/editor/userdata/) +- [控制流](/docs/editor/flow/) +- (施工中) + +文档: + +- [范例](/docs/editor/examples/) +- [API 文档](/docs/editor/api/) + +# 开发者 RTFM 系列 + +首次参与开发松饼,看这个: + +- [如何开始参与开发](/docs/start/) + +各种参考资料: + +- [搭建开发环境](/docs/dev-setup/) +- [Libsaki 代码导读](/docs/libsaki/) +- [松饼 C++ 代码规范](/docs/cpp/) +- [松饼 QML 代码规范](/docs/qml/) ---- -
- -# 配置要求 - -|-----------|---------------------------------------| -| 平台 | 要求 | -|-----------|---------------------------------------| -| Windows | Windows 7 或以上(不支持 XP 和 Vista)| -| Android | Android 4.1 或以上 | -| Linux X11 | 依赖 Qt 5,需要自行编译 | -| macOS | 依赖 Qt 5 和 Xcode,需要自行编译 | -| iOS | 依赖 Qt 5 和 Xcode,需要自行编译 | -|-----------|---------------------------------------| diff --git a/signup-pass.md b/signup-pass.md index 44b6159..aead9c1 100644 --- a/signup-pass.md +++ b/signup-pass.md @@ -5,6 +5,6 @@ permalink: /signup-pass/ --- - 喜大普奔!账号注册成功。 -- **下一步**:回到[入坑步骤](/#newbie),继续入坑。 +- 回到[首页](/)。 diff --git a/signup.md b/signup.md index ec9f29a..73d2c80 100644 --- a/signup.md +++ b/signup.md @@ -125,8 +125,8 @@ table td, table td * { ## 松饼在线功能使用协议 1. 注册账号即视为同意本协议。若不同意,则不应当注册。 -1. 松饼麻雀处于删档测试阶段。平台有权随时无理由删除或修改任何数据。 +1. 松饼麻雀处于删档测试阶段,平台有权随意改动任何数据。 1. 平台对产品和服务不提供任何质量保证。 出现故障,不保证修复;出现损失,无义务赔偿。 -1. 平台不提供任何隐私或安全的保障,对于用户数据(包括密码在内)的泄露不负任何责任。 +1. 平台不提供任何隐私或安全的保障,用户须自行承担数据泄漏的风险。 1. 平台有权随时无理由暂停或终止一切运维。